· 9 years ago · Oct 18, 2016, 04:10 PM
1/* ries.c
2
3 RIES -- Find Algebraic Equations, Given Their Solution
4 Copyright (C) 2000-2016 Robert P. Munafo
5 This is the 2016 Oct 08 version of "ries.c"
6
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 If you got ries.c from the website mrob.com, the GNU General Public
19 License may be retrieved from mrob.com/ries/COPYING.txt
20
21 You may also find a copy of the license at www.gnu.org/licenses/
22
23
24 The remainder of this large header comment is broken up into sections
25 titled: HOW TO BUILD, UNFINISHED WORK, DETAILED NOTES ON ALGORITHM,
26 REVISION HISTORY.
27
28HOW TO BUILD:
29
30 1. Boot your favorite UNIX-compatible computer (Step 0: install Linux,
31 because Linux rules! :-)
32 2. Make a new directory, put this file there.
33 3. Compile it with the following command:
34
35 gcc -o ries ries.c -lm
36
37 If the compilation fails and reports errors like "undefined reference",
38 try moving the pieces around: "gcc ries.c -lm -o ries". Using the order
39 "gcc -o ries -lm ries.c" is known to NOT work with recent versions
40 of GCC.
41
42 Try other flags for optimization if you wish (like: -m64, -O2 or -O3)
43 Note that -ffast-math does *not* work; it prevents IEEE 754 compliance
44 and breaks a few of the RIES algorithms.)
45
46 4. Run ries and give it a number, for example:
47
48 ries 2.5063
49
50BUILD OPTIONS:
51
52In the compile line you may add one or more of these options:
53
54 -DRIES_WANT_LDBL
55 Use this option to 'ask' RIES to use the 'long double' floating-point
56 data type for all calculations. It will try to determine (via other
57 predefined flags provided by the compiler) whether it is available
58 and if so, will use it. This gives a few extra digits of precision on
59 most Intel-based systems, and gives about 30 digits on PowerPC systems.
60 On some systems (notably Cygwin) you'll get errors.
61
62 -DRIES_USE_SA_M64
63 Use this option to make RIES use standalone transcendental functions.
64 These functions are in the separate source file "msal_math64.c", which
65 should be available in the same place you found this source file.
66
67 -DRIES_MAX_EXPRESSION_LENGTH=29
68 Use a maximum expression length of 29 symbols, rather than the default.
69 Longer expressions might be needed if you're using the --one-sided
70 option a lot, but they also increase the amount of memory RIES uses
71 while doing long searches.
72
73BUILDING IN MICROSOFT VISUAL C++
74
75If you want to build RIES in MS Visual Studio, start at the RIES
76website (mrob.com/ries) and follow the "Source code" link. Download
77and save the source file "ries-for-windows.c". Read its header comment
78for further instructions.
79
80RIES INSTRUCTIONS (MANUAL)
81
82Instructions for actually using RIES are in the manual, which
83should be in the same place you found this file, if not look on the
84web at mrob.com/ries
85
86The manual source is in nroff format (ries.1), and should also be
87available in Postscript, PDF, and plain ASCII text. To use the nroff
88version, copy it to the proper place (probably in /usr/share) e.g. :
89
90 cp ries.1 /usr/share/man/man1
91
92(substitute appropriate local manpage directory for your OS) then type
93"man ries".
94
95*/ /*
96
97UNFINISHED WORK (TTD)
98
99(Listed more or less in the order that I want to look at them, and
100recent ones have date tags. Most of the undated notes are from prior
101to December 2011)
102
10320160423
104 Add --surprise-me option, which generates a target value according
105to a suitably-distributed random number generator e.g.
106e^(K*erf(rand(0..1))) where an approximation of the error function
107would be acceptable (see en.wikipedia.org/wiki/Error_function, section
108"Approximation with elementary functions")
109
110 } else if (strcmp(pa_this_arg, "--surprise-me") == 0) {
111 ries_val t;
112 g_surprise_me = B_TRUE;
113
11420150118
115 There is an error in the manual: "... To exit on a match within
116some ``epsilon'', use --max-match-distance with a nonzero epsilon; to
117reject inexact matches use --max-match-distance ..." note that the
118first behaviour does not happen (but would be a nice feature to have).
119The first behaviour is accomplished by the option "-n1". Check
120the rest of the manual for similar errors and make sure "-n1" and
121--{min|max}-match-distance cross-reference each other.
122
1232013.0314 Look into adding two more classes of numbers: -e for
124"elementary" and something like -t for "transcendental". The
125uncertainty has to do with which definitions I wish to use.
126 -e for "elementary" fills the rather wide conceptual gap between -a
127(algebraic) and -l (Liouvillian). I would like to have a class of
128numbers where exponentiation is unrestricted, so sqrt(2)^sqrt(2) would
129be allowed. That is kind of like what we'd get now with "-a
130--any-exponents", but I don't want to allow x in exponents because I
131consider the root of "x^x=2" to be non-elementary. So we need a
132"--no-x-in-exponents" option to do -e the way I envision it. Since
133trig functions are linked to exponents (Euler's formula; complex
134exponential function) it seems to make sense to have a
135"--no-x-in-trig" setting as well (which conveniently also makes
136try_solve's job easier). I should allow e and the exponential function
137but with no x in the exponent; logarithms should also be allowed, but
138with no x inside a logarithm (otherwise we get things like "x*ln(x)=3"
139which is just another form of "x*e^x=e^3"). This only needs one
140setting, that is, --no-x-in-exponents also implies no x in arguments
141to [E], [l] or in either argument of [L].
142 -t would allow everything, and would also enable the W function if
143it is available. The only difference versus -EW is that -t would not
144generate an error when W is not available, but would just silently
145proceed to find W-less solutions.
146
1472013.0314: RIES has trouble finding an equation for
1481.3566631192732151980, which is the root of 2^x+3^x=7. The best I
149could do was "ries -p 1.3566631192732151980 -Sx+-23^5 -l5" which finds
150the awkward "x-(x+2^x+3^x) = (2+2)^(2-3^3)-(2+5)". RIES suffers from
151the LHS always having to start with [x). I could address this by
152removing the LHS-RHS distinction when calling gen_forms, and find a
153different way to regulate the balance between LHS's and RHS's in the
154database. A change like this might be easier (or harder) is it is done
155after (or before) I generalize the handling of restricted symbolsets.
156It also clearly affects the "x on both sides of the equation" change.
157
1582013.0202 --symbol.names is nice, but I need to add definable "begin"
159and "end" strings for various things e.g. superscripts, and start
160looking at user-redefinable fixity and precedence for things like
161mapping [abv] -> "Surd[a,b]" for Mathematica.
162
1632012.0103: One or more custom defined constants.
164 To support this and a future defined-functions feature, each
165user-defined thing needs to have a symbol auto-generated for it out of
166the set of as-yet-unused byte values. Preferably this auto-generated
167symbol will be a unique and yet-unused ASCII letter, but it might have
168to use more than one letter. That means that (in addition to mapping
169functions to turn names into symbols, and additional fields in the
170sym_attr_block structure), I also need a new low-level output
171formatter for -F0 and some of the debug_xxx output to replace the
172simple printf("%s", expr) that I use now..
173 This formatter should turn non-standard symbols into '(Nm)' where
174"Nm" is an abbreviated version of the user's supplied name. This
175symbol can also be used in the -O, -N, and -S options with parentheses
176(which have no purpose in that context), so e.g. '-Op(Eg)' would allow
177pi and the user-defined symbol 'Eg' to be used once each. To avoid
178ambiguity the symbol might have to be auto-generated, and to avoid
179driving users nuts I can give them hints on how to avoid that.
180 Constants and (eventually) functions can share a common FORTH-like
181syntax. Note the optional weight and abbreviation fields just before
182the full name:
183 # x e^-(x^2) is the inverse of Gosper's "Dilbert Lambda Function"
184 --define : InverseDilbertLambda ( x -- x e^-(x^2) )
185 dup dup* neg exp *
186 ;
187 --define : XeX ( x -- x*e^x ) dup exp * ;
188 --define : Eg:EulerGamma # seft-a (constant)
189 ( -- The Euler-Mascheroni constant, 0.57721... )
190 ( --value-type TRAN )
191 # 50 digits for when RIES goes to higher precision
192 0.57721566490153286060651209008240243104215933593992
193 ;
194 --define : 14:H:Hypot # seft-c (two-argument function), weight 14
195 ( a b -- sqrt(a^2+b^2) )
196 dup* # ( a b^2 )
197 swap # ( b^2 a )
198 dup* + sqrt
199 ;
200 Note that the FORTH comment delimiter is parentheses, which fits
201nicely with the fact that parentheses are unneeded in postfix
202expressions.
203 In the first implementation of functions, you cannot include literal
204constants in the function, but instead have to --define the constant
205first with its own name.
206 2014.1122: Everything in comments would be ignored except a token
207starting with '--', like the ( --value-type TRAN ) example above. This
208allows me to extend the FORTH syntax to deliver optional metadata. If
209a constant has no explicitly given --value-type, it would be guessed
210using guess_valtype() as is currently done with the target. Advanced
211users who are making collections of constants in -p files would define
212a --value-type for all.
213 2012.0613: I might also want to allow immediate constants in
214--eval-expression strings (and thus, in eval()) delimited by parentheses
215or whitespace. If using parentheses, "ries --eval-expression '(27)q'"
216would produce similar output to "ries 27 --eval-expression xq" or
217"ries --eval-expression '33^q'". This improvement would be done along
218with a loosening of the just-mentioned restriction on using immediates
219within functions.
220
2212013.0228 Add DUP, SWAP and OVER operators. These require a bit of
222modification to the stack depth and undo handling, but they are
223similar enough to seft-a and seft-b that it shouldn't be too hard.
224With a default complexity about the same as a small integer, they
225would allow duplication of common subexpressions, which seems to
226happen fairly often in real formulas.
227
2282013.0314 More creative use of attribute tags (TAG_INT, TAG_RAT, etc):
229 --only-integer-exponents: exponents must be integer if the
230argument does not contain x, and roots must be integer if the
231argument *does* contain x, and all others are disallowed.
232 2013.0309:
233 --unit-fractions option: reciprocal only if argument is integer
234(possibly useful for Egyptian fractions work)
235
2362012.1222 Allow all odd integer roots of a negative argument (3
237currently allowed, but better if any odd integer were detected, tags
238should help with this; requires extra wizardry in try_solve); add an
239option to display "3,/(...)" as "cbrt(...)" (Unicode handled separately
240with a .ries profile)
241
2422016.0131 The "unicode.ries" profile is disappointing for a few reasons:
243 * The legend at the bottom of RIES' output still uses the standard
244 ASCII symbols
245 * sqrt(2) becomes "/(2)" (where / is the radical sign) but the parens
246 shouldn't be there if the argument is only one character long
247 * Nth root, e.g. 3,/7 for cube root, should use a "3" superscript or
248 the Unicode cobe-root symbol (U+221B), and other special cases
249For all of these we need some sort of user-definable cascading list of
250transformation rules.
251
2522013.0205 Output format option that prints any integer-valued
253subexpression as an integer, so that "ries -s -l3 351.36306009596398"
254can give "8 sqrt(1929)" instead of "8 sqrt((5-7^2)^2-7)". Attribute
255tag should help with this, but infix conversion will need to call
256eval() on subexpressions to figure out when a given subexpression can
257be substituted with an integer (and recursive calls to infix
258conversion pruned).
259
2602012.1222: In --one-sided mode we could take multiple targets, enter
261them all in the database as [x], and use the existing algorithm which
262would thereby compare every match to each target. This requires a
263significant change to exec() in that it must get its exec_x from a
264(new) field in the pe, since the "x" value differs from one expression
265to another.
266 For --one-sided mode (with a single target or with multiple targets)
267we really don't need a database at all: every generated expression can
268just be compared to x on-the-fly. This would save memory and run all
269in cache, possibly much faster, and allow for a simple multi-threaded
270implementation. This can be combined with the multiple targets
271improvement (in which case there would be a small database containing
272the [x] expression for each target).
273
2742013.0305: A similar idea to the "multiple targets" idea is a
275"correlation search" operating mode. In this mode there are just two
276targets T and U, and all expressions contain one or the other; any
277match must have a T expression on the LHS and a U expression on the
278RHS. This is like one-sided mode except that everything is an LHS, and
279it's like the planned "x on both sides of the equation" mode in that
280matches need to deal with both sides of the equation having a
281derivative. One big difference is that the derivative with respect to
282T might be independent of the derivative with respect to U (or they
283might be partly correlated, or anti-correlated). Thus, each reported
284match would report the "delta" as a vector (with direction and
285magnitude) encoding how far and in what direction each of the two
286targets T and U need to be altered to make that particular equation
287match.
288
2892013.0307: If exiting because of a parameter error, display a
290traceback with the name(s) and character offsets of any include files
291(Line numbers would be nice too, but might be difficult).
292
2932012.1207: Review implementation of --try-solve-for-x:
294 * Inverse trig functions are multi-branched. (If they give 7.012913
295we might find "sin(x) = 2/3", when solving that for x we must recognize
296it and solve to "x = arcsin(2/3)+2 pi" rather than just "x = arcsin(2/3)").
297 * Add new options --LHS-addsym, --LHS-onlysyms, --LHS-onesym, and
298--LHS-nosyms specify the symbol-set for LHS generation (and likewise
299for RHS). This is a refactoring, to prepare for the next changes.
300 * The -S and -N options need to have a different meaning when solving
301for x. sym.attrs[i].sa_alwd (FKA sym_allowed) needs to be split into
302LHS and RHS parts (to provide for the fact that, when solving, some
303operators become their inverses: thus the option -SE should set
304LHS.allowed['l'] and RHS.allowed['E'] to nonzero values).
305 * To provide compatibility, the -S, -E, -O, and -N options work the
306old way unless followed by an '=' character. For example, '-N=q' will
307forbid sqrt in RHS and forbid x^2 in LHS.
308 * Likewise, the symbol-related variables, like a_minw etc. need to be
309duplicated so we have one set for LHS and another for RHS.
310 * The sym_allowed handling needs to be even more subtle for LHS
311expressions: In the expression [xl3^23/-], the [23/] will move
312unchanged to the RHS, whereas the [l], [3^] and [-] will get changed
313into [E], [3v] and [+] respectively on the RHS. The way to handle this
314is for ge.2 to look at whether the argument(s) contain x (by testing
315dx!=0) and can also take the current stack pointer into account when
316deciding whether to add a symbol. For seft-b symbols like [l], if the
317value on the stack contains x (or if the SP is precisely 1) then the
318LHS sym_allowed array should be used, but if the SP is bigger than 1
319the RHS sym_allowed should be used. Likewise the seft-c symbols should
320check if the SP is precisely 2. This also implies that in
321--solve-for-x mode the gf_1 and ge.1 complexity limits need to be
322based on the union of LHS and RHS symbolsets.
323 * Dealing with extra x's in the equation. Options include:
324 - Use of -s implies or requires -Ox
325 - Use of -s implies or requires the "X only on LHS" mode (opposite of
326allowing x on both sides of an equation)
327 - Continue with the current practice of simply pushing any extra
328x's over to the RHS.
329 * Dealing with trig functions. The options are:
330 - Adding inverse trig functions, which would clutter the search
331space even more.
332 - Use of -s implicitly disables trig functions only on LHS (you can
333explicitly enable them with an --LHS-syms option)
334 - Use of -s implicitly disables trig functions, and/or implicitly
335enables their inverses (which would be disabled by default)
336 - Use of -s shifts the weights of trig functions to make them less
337dense in the search space
338 Perhaps these different options could be selected via an extra letter
339after the -s
340 * The -O option, or any similar option setting a specific non-zero
341limit on the number of a particular symbol, cannot be implemented
342efficiently. (Consider what happens if all expressions are inserted
343into the same tree: then for any given expression, a large fraction of
344the other expressions in the tree cannot be used to make a valid
345solution: If we get "ln(x)=e^2" and solve for x, and they gave the
346option -OE, that solution is not valid). To resolve this, the best
347solution is probably to make "solve for x" mutually exclusive to the
348-O option. As a sole exception, -Ox can still be implemented, so long
349as all reported results involve just a single LHS and an RHS.
350 * 2013.0215: One-sided simplification/reduction rules similar to
351those already in cv.simplify. One simple example is [ss]->[4^]. A lot
352of these are already implicit in the pruning rules, so I can look in
353the comments next to the add_rule() calls to get the list of
354simplifications. Virtually all will be simple string substitutions.
355The unsimplified forms show up only when using -s.
356
357*/ /*
358
3592012.0503 (partly done on 20120505): Prior to 20120505, "ries -l-2 -i
360143" gave the bizarre answer "(x-2)+3 = (3*4)^2". The "(x-2)+3"
361(instead of x+1) results from the k_sig_loss value 0.01: Because 1 is
362less than 143*k_sig_loss, RIES doesn't want to perform the addition
363x+1. Similarly, "ries 7775" fails to find "x+1=6^5" because it doesn't
364want to add 1 (or any integer) to x.
365 The narrower, safer fix (implemented on 2012.0505) is to attempt
366"(x+1)-1" and see if it is precisely equal to x. If so, then we can
367assert that no significance loss has actually occurred, and permit an
368exception to the k_sig_loss rule for addition/subtraction. Other
369similar "conservative" tests might be possible, but add/subtract is
370the big one.
371 A broader fix to investigate is to always allow f(x)+K whenever the
372variable subexpression f(x) is larger in magnitude than the constant
373subexpression K. That will require testing with #qualify#.
374
3752012.0511 (partly done on 20120720): The "four 4's problem" and many
376others like it are small enough to implement with --one.sided and/or
377--numeric.anagram. RIES's handling of these problems can be improved
378with fairly little modification:
379 * An option to not use rules like [xx/] that are meant to prune
380"redundant" subexpressions like "4/4".
381 * As a separate option (perhaps by giving "--numeric.anagram" vs.
382"--strict-numeric-anagram"), accept an expression only if all of the
383symbols have been "used up" in the expression. This will require
384changing the "exhaustion timeout" detection: I can probably use a
385"Still searching" message similar to the one I added to handle
386--max-match.distance.
387
3882012.0520: Presently the report.match routine has a bunch of arrays
389called {r|l}_{e|f|g}scratch, and the escratch ones are being used for
390two different purposes (char[] and symbol[]). The names should be
391improved, and a dedicated symbol[] scratch array added. These changes
392are logically combined with -Fmax, -FHTML, etc. output formats:
393
3942013.0314: Augment --symbol.names in whatever ways are needed for a
395user to implement output formats such as: raw symbols,
396calculator-keys, HTML, RHTF, TeX, eqn, Maxima, etc.
397 Each symbol should have a user-definable precedence, associativity
398and layout (like Haskell "fixity"). If desired, an operator like *
399(seft 'c', FORTH stack effect (a b -- c) ) could be redefined to be
400displayed as any of the following:
401
402 arg_order s_0 s_1 s_2
403 Lisp: (times a b) a, b '(times ' ' ' ')'
404 RIES: ba* b, a '' '' '*'
405 infix: a x b a, b '' ' x ' ''
406 HTML: a×b a, b '' '×' ''
407
408There also need to be flags indicating when things can be left out, as
409is presently done with '*' in certain cases, and indicating when
410parentheses can be left out, as is presently done with a product
411inside a sum.
412 It is important to note that user-defined functions leaving more
413than one item on the FORTH stack cannot be expressed in infix. (If the
414two outputs of a single function are immediately multipled together,
415what goes on each side of the multiplication sign? It's even worse
416when things are done to some of the outputs before they are combined.)
417
4182011.1226: Consolidate the (current) multiple ways that roundoff, overflow,
419loss of significance, and tautology errors are handled. This involves the
420constants and variables: n_ovr, p_ovr, k_sin_clip, k_min_best.match,
421k.vanished_dx, k_prune.deriv, and k_sig_loss. For example,
422k_sig_loss*k_min_best.match should be equal to the magnitude of the
423"machine epsilon" (2^-53 in the case of 64-bit double) determined by
424init.formats().
425
4262012.0106: More importantly, we need to allow matches between an LHS and
427another LHS (producing solutions with X on both sides of the
428equation). The match closeness becomes |(val_r - val_l)/(deriv_l -
429deriv_r)| which is the same as the current formula except for the
430addition of the deriv_r term.
431 * (2011.1226) Start at the bottom (exec(), eval(), newton(), etc.) and work my
432way up to the top (ge.1() etc.). Rename variables and parameters (like
433the "!on_rhs" passed to exec() from ge.2) so the names agree with what
434they actually do ("!on_rhs" should be something like "!no_x" or
435"has_x").
436 * Allow more user control over how much output contains x on both
437sides, from old behaviour to "all eqns have x on both sides". The
438default should be somewhere in the middle; this should be implemented
439in the main outer loop where it tests "if (lhs_insert > rhs_insert)".
440Also, the 'solve for x' and '-Ox' options should both force the old
441behaviour (the latter because of the need to have different
442sym.attrs[i].sa_alwd values for LHS vs. RHS).
443
4442011.1226: Higher precision:
445 * (partly implemented on 2013.0301) On Intel targets in GCC 4.2.1,
446__LDBL_MANT_DIG__ is 64, implying that I can use "long double" to get
447a bit more precision. To exploit this I will need to do runtime
448testing to determine what precision I am actually getting, similar to
449the code in hint.c
450 * (complete by 2013.0626) Continue conversion to use of long double
451and runtime adjustment of epsilons and cutoffs.
452 * Add string-to-float and float-to-string conversion routines based
453on f107_spfg and f107_sscan in f107_o.cpp. (I think these already
454handle the exponent adequately, but I'll want smarter handling of
455extra whitespace when there is no exponent). Convert all instances of
456double printf and scanf to use these routines (including the debug_X
457printfs).
458 * Use three sets of flags:
459 Desired precision: RIES_WANT_F53, RIES_WANT_F64 and RIES_WANT_F107;
460 also RIES_WANT_LDBL etc. for users who don't know what their 'long
461 double' precision but still want to use it.
462 Available types and their precisions: RIES_HAVE_LDBL_F64,
463 RIES_HAVE_LDBL_F107 and RIES_HAVE_F128
464 Which type to use: RIES_VAL_DBL, RIES_VAL_LDBL and RIES_VAL_F128
465 * Don't bother with C++; just use __float128 if it's available and
466too bad if it's not.
467 * No need to use macros like MUL(src1,src2,dst) because __float128 and
468'long double' have fully implemented builtins.
469 * Initialize the special constants (k.vanished_dx, k_prune.deriv,
470etc.) differently depending on precision option. It should be possible
471to add these gradually without breaking normal precision since the
472rest of the code will just ignore the lower half of any quad
473variables.
474
475Consider options for utilizing multiple processors (threads / parallel
476implementation). {As of 2012.0423} I have identified three possible
477paths of development, below titled "Best", "Good" and "BAD":
478
4792012.0423: Best: Perform additional searching *without* expanding the database.
480This would be done when the memory limit is reached (perhaps in
481response to a user option):
482 - Walk the tree, applying all possible monadic transforms to each
483node, to see if the result then produces a new match to another
484existing node. For these purposes a "monadic transform" consists of
485appending *either* a single seft-b symbol, *or* a seft-a followed by a
486seft-c. For example, if this scan found [43L] in the tree, it would
487append 's' to form the expression [43Ls], compute its value (which is
4881.592289...) then search the tree for this value using a bt_find()
489function. It might then find [xp/], which would be a near-match in the
490case of x=5. This type of search can be efficiently parallelized by
491having each of N threads traverse 1/N part of the tree. (Which in turn
492suggests that we should maintain population-counts at each node and
493add a bt_index() routine.)
494 - Greater-complexity expressions can be synthesized by appending a
495short, low-complexity complete subexpression and a seft-c symbol.
496For example, [43L] : [3q] : [+] => [43L3q+], which would then match
497[x2-].
498
4992012.0109: Good, but hard to implement, and very memory-intensive:
500 Within each petit-cycle, have N threads
501running at any one time, each constraining itself to a part of the
502expression search-space, distinguished by the first few symbols in the
503expression. For example, after the complexity depth has gotten high
504enough, we will have identified all possible combinations for the
505first 3 symbols in the expression's postfix representation. The
506searchspace can then be partitioned by having ge.2 perform a CRC
507hashfunction on the first 3 symbols, and determine whether it should
508prune or recurse depending on the low log_2(N) bits of the hash value.
509 This requires having each task build up its own binary tree, which
510in turn requires a parallel binary tree merge. For example, using 4
511threads, each with its own binary tree divided into quartiles:
512 * Add population-counts to each tree node and add a bt_index()
513routine;
514 * When it is time to merge, each of the 4 trees becomes read-only;
515 * Each of 4 threads then builds up a new tree consisting of the I'th
516quartiles of each of the old trees;
517 * Combine these 4 new trees into a single big tree by creating 2 dummy
518parent nodes and 1 dummy grandfather node;
519 * Deallocate the old trees.
520 The main problem with this approach is that it uses twice as much
521memory during the merge process, and 4 times as much memory bandwidth;
522and (more crucially) there is no clear way to determine in advance
523whether there will be enough free memory to perform the merge.
524
5252014.1122: Good, and a little less hard to implement:
526 Run in normal single-threaded mode until the tree is big enough to
527survey the location of quartiles as in the 2012.0109 proposal. Then,
528permanently split the tree into N pieces (probably by a simple
529traverse-and-copy). On subsequent patit-cycles, run N threads where
530each thread imposes its own values of g_min_equ_val and g_max_equ_val.
531Threads will find duplicate solutions, but are not fully redundant; as
532a rough guess I imagine it will have a factor of sqrt(N) of
533ineffeciency, so a 4-thread system will use 2 times as much memory
534to find the same answers in half as much time.
535
5362012.0423: BAD: The following does *not* work because of the elaborate
537interleaved nature of the bt.insert algorithm (see note in oldries.c
538mentioning "memory performance degradation"), however it could if we
539return to the older 2-tree implementation.
540 - Have 2 scans running at any one time, an RHS scan and a LHS scan.
541Whenever a scan completes, initiate another. Every time a scan
542completes, another thread runs through the outputs of the latest RHS
543and LHS.
544
545%%% options to add:
546
5472009.0603: Higher complexity scores for trig functions unless argument
548expression contains pi or x. {This was mostly addressed by the trig
549argument scale change on 2011.1229}
550
5512012.0102: Warren Smith suggests, "I dont mind sin(1), but sin(1) IN
552AN EXPONENT like 3^sin(1) is just ridiculous.", suggesting an idea
553like tables of rules that match the end of a forth subexpression (1S^
554in this example) and if matched, either prune it outright or add to
555the complexity score. (If adding to the complexity score, the
556possibility of this has to be considered by the bounds-setting and
557short-circuit recursion code). After further discussion he suggested
558that no subexpression should be completely excluded, but an "entropy
559function" should be used to weight entire expressions based on the
560likelihood they would be found in actual maths. Things like 1S^ would
561get a really high weight, and the expression database would be
562"exponentially" more efficient at covering the types of expressions he
563is interested in.
564 This is distinct from --rational-trig-args, which only allows
565all-or-nothing pruning. However, Warren's idea could be used by adding
566an Identity-like operator that has a symbol weight and has the effect
567of adding a "blessed" tag to the value. Once blessed, the value would
568then be eligible for use in an exponent.
569
5702012.0103: --log-base option to do for ln what --trig-argument-scale
571does for sine and cosine.
572
573*/ /*
574
575Ideas from 2007.0703 or earlier (all of these are in MBP's first
576backup, old PMG5 archives seem to have nothing; old iMac-G4 archives
577might have more info):
578
579variations on -l that allow specifying limit of search by
580precision, by time, by memory usage, or by number of equations tested.
581The present -l is usually correlated with all of these but is never
582equal to any of them. ('-lmem=10M', '-ltime=20m', '-ldigits=8',
583'-lexprs=3e6', -leqns=1e10', etc.) --max.memory is a different because
584a small -l will still cause RIES to exit before the indicated amount
585of memory is used.
586
587%%% command-line option: if no symbol '1', then 'r' shouldn't be
588allowed. Likewise for '2' + '^' and 's'; '-' and 'n'; 'e' + '^' and
589'E'; others? Which should be the default, the current simpler behavior or the
590"more correct" behavior? The "simple" behavior is useful, as
591illustrated by the 1.4142135 example in the manpage, because it
592helps people find alternate ways to express the same solution.
593
594macros (user-defined constants and functions):
595 - use a separate symbolset namespace (implies macros cannot call
596themselves or each other, which avoids lots of problems)
597 - To use -O with a macro, include '_' in the -O symbolset
598list; all symbols after '_' are macro names. -S assumes all macros
599(why would you define a macro and not want to use it?); using -N
600with a macro is a contradiction.
601 - Macro can use any symbols, and symbols used within macro
602expansions don't count against their sa.alwd (FKA sym_allowed) quotas
603(this is probably easy; just need to make sure)
604 - Need to implement stack-overflow detection in the metastack
605routines, both for the stack and for the undo lists.
606 - Test evaluator routine needs to make sure macros fit one of the
607three allowed types ('a', 'b' or 'c') and that only types 'b' and 'c'
608dip into the stack's current contents.
609 - Type 'a' can be "precompiled" since they amount to custom
610constants
611 - Should I allow immediate operands (like 0.577...) to facilitate
612defining constants that can't be computed any other way? How about
613special operators, like 'exch'?
614 - execution can probably be accomplished by having eval() call
615itself recursively. It needs to handle its own error returns.
616
617 - with many -i test cases the RHS expression totals are a lot bigger
618than the LHS totals (while the insert totals are equal). There are
619probably cases that come out the other way around, too. In cases like
620this, the program could probably find more matches more quickly by
621shifting the balance between LHS/RHS to favor the side that is
622generating and inserting more expressions per unit time. (The present
623implementation tests "lhs_insert > rhs_insert" which is usually the
624best way to do it.) I could model this with formulas that take into
625account the total amount of dead-ends, expressions, and inserts on
626both sides, compared as a ratio to the equation total (and take the
6271st derivative to figure out what side of the maximum you're on). The
628idea is to maximize the number of full equations found per unit time
629rather than keeping the number of LHS inserts equal to the number of
630RHS inserts.
631 - here's a way to allow printing more than one exact solution: When
632inserting an LHS or RHS, if an identical item already exists in the
633tree, overwrite it with the new one. This will cause at most one new,
634distinct exact match per matchscan. Since this new match is of higher
635aggregate complexity than the old one, it has at least a moderate
636chance of being a mathematically distinct solution (-:
637 - spend a lot of time looking at which expressions are generated
638first, and try to improve the weights so it makes more sense. Why does
6392.5063 find [x2q/]=[pq] before [xs]=[p2*]?
640 - add constants: Feigenbaum, Euler's
641 - add Gamma function (many notes on this below) with an option to
642use "factorial" notation when displaying.
643 - explore how to expand RIES to complex numbers and complex analytic
644functions. Looks easy -- after all, complex data types are native in
645GCC!
646
647(Test cases are now in #qualify#)
648
649*/ /*
650
651TABLE OF FUNCTIONS
652
653 sym stack-effect description
654 0x1 -- Phantom symbol for argument-reversed version of -
655 0x2 -- Phantom symbol for argument-reversed version of /
656 0x4 -- Phantom symbol for argument-reversed version of ^
657
658 ' ' -- Blank space: no operation (for --eval-expression)
659 0 (-- 0) The constant 0.0 (not currently used, but will have a
660 role soon as part of --numeric.anagram)
661 1 (-- 1) The constant 1.0
662 2 (-- 2) The constant 2.0
663 3 (-- 3) The constant 3.0
664 4 (-- 4) The constant 4.0
665 5 (-- 5) The constant 5.0
666 6 (-- 6) The constant 6.0
667 7 (-- 7) The constant 7.0
668 8 (-- 8) The constant 8.0
669 9 (-- 9) The constant 9.0
670 ! (a -- f) Factorial monad f(x) = x! = Gamma[x+1] (reserved, not
671 yet implemented)
672 # (n d -- x) Digit paste operator x(n,d) = 10*n+d (reserved, not yet
673 implemented. This is to make --numeric.anagram more useful)
674 % (a b -- m) (reserved for modulo or remainder?)
675 ^ (a b -- f) Power: f(a,b) = a^b
676 * (a b -- p) Multiply+ p(a,b) = a*b
677 ( -- Comment delimiter; used to bracket custom symbol names;
678 used as a placeholder during infix translation
679 ) -- Comment delimiter; used to bracket custom symbol names;
680 used as a placeholder during infix translation
681 - (a b -- d) Subtract: d(a,b) = a-b
682 + (a b -- s) Add: s(a,b) = a+b
683 : -- Function definition start
684 ; -- Function definition end
685 . -- Placeholder for multiplication during infix formatting
686 / (a b -- r) Divide: r(a,b) = a/b
687 A (x -- a) Arctangent a(x) = atan(x) (reserved, not yet used)
688 C (x -- c) Cosine c(x) = cos(pi x)
689 E (x -- f) Exponential function f(x) = e^x
690 G (x -- g) Gamma function g(x) = Gamma[x] = (x-1)! (reserved, not
691 yet implemented)
692 I (x -- x) Identity function x(x) = x (not used in expressions, but
693 used as a placeholder during infix translation)
694 L (a b -- l) Arbitrary logarithm l(a,b) = log_b(a)
695 S (x -- s) Sine s(x) = sin(pi x)
696 T (x -- t) Tangent t(x) = tan(pi x)
697 W (x -- w) Lambert W function, e.g. w(10.0) = 1.74553...
698 e (-- e) The constant 2.71828...
699 f (-- f) The constant 1.61803...
700 l (a -- l) Natural logarithm: l(a) = ln(a)
701 n (a -- n) Negate: n(a) = -a
702 p (-- p) The constant 3.14159...
703 q (a -- q) Square root: q(a) = sqrt(a)
704 r (a -- r) Reciprocal: r(a) = 1/a
705 s (a -- s) Square: s(a) = a*a
706 v (a b -- v) Root: v(a,b) = a^(1/b)
707 x (-- x) The user's target number
708
709*/ /*
710
711ARCHITECTURE
712
713 main -- Outer loop -- increment complexity and decide whether to add to
714 RHS tree or LHS tree
715 gen_forms -- setup first recursive level of gf_1
716 gf_1 -- Add a symbol of type 'a', 'b' or 'c' and recurse if complexity
717 : allows
718 :.gf_1 -- Recursive levels until form is complete
719 ge_1 -- setup metastack and initial level of ge.2
720 ge_2 -- Generate one step of FORTH code and update metastack,
721 : recurse if more symbols in the form
722 :.ge_2 -- Recursive levels until form is complete
723 canonval -- Try to put expression value in [1.0,2.0) (only if
724 --canon-reduction option is used)
725 bt_insert -- Insert calculated result into LHS or RHS tree
726 check_exact_match (called for exact matches)
727 report_match -- Display match without doing Newton
728 check_sides -- Find closest neighbor of the opposite sidedness
729 and determine if the pair sets a new record.
730 check_match -- Check a single pair to see if it's a new
731 solution
732 cv_simplify -- Simplify equation by removing e.g. "2*"
733 from both sides
734 newton -- Use Newton's Method to locate ideal value of
735 x for a given solution
736 report_match -- Display a match that converged by
737 Newton.
738 try_solve -- Try to convert "expr1 = expr2" into
739 "x = bigexpr"
740
741DETAILED NOTES ON ALGORITHM
742
743To reduce the search time, the graph theory "bidirectional search"
744(also called "meet-in-the-middle") technique is used. Rather than
745attempting to search for solutions of the form
746
747 X = expression (1)
748
749it searches for solutions of the form
750
751 f(X) = expression (2)
752
753where f(X) represents an expression containing X. Each side of
754equation (2) is represented as a set (in memory, a ordered list,
755implemented with a binary tree) of expressions and their values. Thus
756there are two lists {For efficiency, these two lists are stored in a
757single binary tree, so that I can check for a match after every new
758insert. With a single tree, matching items end up being close to each
759other in the tree}. Each list is kept in order by numerical value.
760Then, the lists can easily be scanned to locate any matches. A match
761consists of an element in the left-hand list whose value is close to
762that of an element of the right-hand list. Keeping the lists in order
763also allows duplicate expressions, like "2*pi", "pi+pi", and "pi*2",
764to be ignored, because they will end up having the same value and
765therefore end up being in the same spot in the list.
766
767It is important to look for "simpler" matches before going to more
768complex ones. Thus, expressions have a complexity score, computed by
769assigning a certain number of points to each of the symbols in the
770exression. Matches are checked in order of increasing total complexity
771(which is the complexity of the left-hand side plus that of the
772right-hand side)
773
774In order to avoid the sorting problems necessary to search the
775expressions in a perfectly increasing complexity order, complexity
776scores are lumped into discrete finite quanta, which are actually
777implemented by using small integers for each component of a complexity
778score, rather than real numbers.
779
780This does not actually cause everything to be searched in order, even
781modulo the quantization errors. Some equations can be represented in
782an unbalanced form with lower aggregate complexity than the
783least-complex balanced form: an example is the cube root of 2: The
784solutions are "x^3 = 2" and "x = 3,/2", both are unbalanced because
785there is one symbol on one side of the = sign and three symbols on the
786other. (",/" is the "Nth root" symbol). There are no good balanced
787solutions. In such cases the unbalanced, low-complexity form will show
788up later in the search than it "should".
789
790*/ /*
791
792To make generation and evaluation easy, expressions are represented in
793a FORTH-like syntax with one character per symbol. Thus, "11+" is 1+1,
794"2q" is sqrt(2), "ep^" is e^pi, etc. Symbols are categorized by their
795stack-effect, which is abbreviated "seft" in the code.
796
797In the actual FORTH language, the stack effect (seft) encapsulates
798what a word does to the stack. It is described by a comment (some text in
799parentheses) containing: the stack contents before the word is executed,
800a "--" symbol, and the stack contents after the word executes.
801
802There are three sefts in ries:
803
804 seft 0: ( -- )
805 No operation (compare to b, b2 which don't change the stack level
806 but do use something on the stack)
807
808 seft a: ( -- K )
809 Adds one thing (a constant) to the top of the stack
810
811 seft a2: ( arg1 -- res1 res2 )
812 Takes one value from the stack, performs an operation, and puts two
813 results back on the stack. (Examples: DUP, divmod)
814
815 seft a3: ( arg1 arg2 -- res1 res2 res3 )
816 Takes two values from the stack, performs an operation, and puts three
817 results back on the stack. (Example: OVER)
818
819 seft b: ( arg -- result )
820 Takes one value from the stack, performs an operation, and puts one
821 result on the stack
822
823 seft b2: ( arg1 arg2 -- res1 res2 )
824 Takes two values from the stack, performs an operation, and puts two
825 results back on the stack. (Examples: SWAP, polar to rectangular conversion)
826
827 seft c: ( arg1 arg2 -- result )
828 Takes two values from the stack, performs an operation, and puts one
829 result on the stack (Examples: DROP, most binary operators)
830
831The RIES symbols of each seft are:
832
833 0: ' ' (blank space)
834
835 a: x 1 2 p 3 e 4 5 f 6 7 8 9 (x, the digits, and the constants pi, e and phi)
836
837 b: r s q l n S C T I (reciprocal, squared, square root, ln, negate, sine,
838 cosine, tangent, identity)
839
840 c: + - * / ^ v L (add, subtract, multiply, divide, exponent, root, logarithm)
841
842For ease in debugging, most symbols have letters that make sense, but
843not always (e.g. "f" for phi, the golden ratio; "v" for root, which
844is meant to represent the v-shaped part of the standard root sign).
845The only constants are the digits 1 through 9 -- no zero, and no
846multidigits or decimal fractions. To get 10 you have to do "25*" or
847something similar; for 1.5 you have to do "32/". A fair amount of
848effort has been put into setting the symbol scores such that the score
849of "25*" is only a little higher than the score for "9".
850
851example cases for deriving the symbol weights:
852
853 (+) ~= (*) (because both occur equally often)
854 (-) > (+), but not by much
855 1, 2, 3, 4, 5, ... degrade gracefully and kind of like a slide rule
856 (14*) = (22*), etc. (implies (n) proportional to log(n) for 1<=n<=9)
857 (33*) = (9) (implies (*) = [..] where [..] is the weight of any two symbols)
858 (25*) > (9), but only by a little (no problems so far)
859 [2q] ~= [5] :: therefore (2q) + [.] ~= (5)
860 [x2v] = [xq] :: (2v) + [.] = (q)
861 [x2^] = [xs] :: (2^) + [.] = (s)
862 [99+] can be >> [55*] (because smaller numbers are more likely)
863
864%%% complexity score for a symbol can be context sensitive, e.g. 'l'
865takes a higher score the second time it is used in an equation -- so
866long as its range of possible scores is within the total range for its
867seft. This might be a good way to eliminate some of the nonintuitive
868aspects of the current system.
869
870Once a set of symbol scores is worked out, it can be adjusted by
871adding any constant to all the values (this adds a bias for long
872expressions, or a bias against long expressions. In the above
873"normalized" examples there is no bias, but the shorter ones will get
874generated first anyway.)
875
876The lists start out small and grow as the program searches. On the
877first pass, the left-hand list consists simply of {X}, the single-
878element expression for the search value, and the right-hand list
879consists only of a few common constants, for example {1, 2, *e*,
880*pi*}. After a few passes the left-hand list will include things like
881"xv" (sqrt(x)) and "x1+" (x+1), and the right-hand side will have
882similar forms such as "2v" (sqrt(2)) and "23/" (2/3). At that point,
883if X is 4/9 a match will be found between "xv" and "23/", even though
884the combination of "x" and "49/" has fewer symbols overall, because
885the former matching is more evenly balanced. Another way of saying
886this is that, since the complexity scores of "xv" and "23/" are both
887lower than the score of "49/", the "xv = 23/" matching is found before
888"49/" even gets a chance to be generated.
889
890To minimize time spent generating nonsense expressions, expressions
891are generated from "forms". A "form" is a symbolic expression of
892expression syntax, like "aabc" for "12q+". Each letter represents a
893different type of stack operation (called "seft" above). Type "a"
894pushes one item, type "b" leaves the stack with the same number of
895items, and "c" leaves the stack with one less item. A form is legal if
896the stack depth (the "a" count minus the "c" count) is > 0 at all
897times and = 1 at the end. Thus all forms start with an "a". The number
898of forms for N={1,2,3,...,8} is {1,1,2,4,9,21,51,127} (the Motzkin
899numbers; Sloane's A1006). By comparison, the total number of forms
900without these restrictions would be 3^(N-1):
901{1,3,9,27,81,242,729,2401}. The savings is considerable. In the
902left-hand list the first symbol will be an "x" in all generated
903expressions. Forms are generated on the fly and never stored in
904memory. As the search proceeds, longer forms are generated as needed.
905
906For each form there is a "minimum" expression and a "maximum"
907expression, as rated by complexity score. For example, "x1+" is the
908minimum expression for form "aac" and "99L" (log base 9 of 9) is the
909maximum. These minimum and maximum expressions are easy to find,
910because each symbol has its own score and the expression score is just
911the sum of the symbol score. Thus it is easy to determine, at the
912beginning of each pass, which forms can generate expressions that are
913within the current complexity range.
914
915Expressions are generated from each valid form. The generation of
916expressions uses a recursive backtracking algorithm, starting with the
917first symbol and moving to the right. At each step, it checks to see
918of the symbols we have so far still allow an expression which falls
919within the complexity range -- if not, the latest symbol is dropped or
920changed. It also avoids generating certain patterns of symbols which
921would be of no computational value, or which are always equivalent to
922a different (sometimes shorter) set of symbols. Examples of this
923optimization are:
924
925 - "aa-" for any seft a symbol would be 0, so is not generated.
926
927 - "aa+" is the same as "a2*", so is not generated.
928
929 - "aa*" is the same as "as", so is not generated.
930
931 - "aa/" and "aal" are equivalent to 1, and are not generated.
932
933 - Almost any operator after "1" is not generated ("1x", "1/", "1r",
934"1^", "1v", "1l", "1L", "1v" all do nothing useful)
935
936 - "2^" and "2v" are equivalent to "s" and "q" respectively, and are
937not generated.
938
939 - "pS" is equivalent to 0
940
941 - "sq", "qs", "nn", "rr" all amount to nothing and are not generated.
942
943The expressions are also evaluated while they are being generated. Any
944subexpression that causes an error, such as divide-by-zero, can be
945skipped along with all expressions that start with that subexpression.
946For example, any expression starting with a constant followed by "nq",
947such as "2nq" which means "sqrt(-2)", will be skipped.
948
949As the search proceeds, each equation (that is, each combination of an
950LHS with an RHS) is checked to see what value X would have to be for
951the equation to work out perfectly, and the difference between this X
952and the user's supplied number is called the "delta". An equation
953becomes a "record-setter" if its delta is smaller than any delta seen
954so far.
955
956If a strict "non-fuzzy" comparison were made, due to roundoff errors
957it would be possible for the same solution to be found twice. For
958example, if X is near 4/9 = 0.44444.., two solutions are "x = 49/" and
959"xq = 23/". One solution might be printed after the other because of
960roundoff in the square-root operation. To avoid this, every time a new
961record-setter is found, the criterion for another record is set to
9620.999 times the new delta.
963
964Determining the value of X for which the equation works out perfectly
965is a hard problem. In theory one would have to solve the equation for
966X. That involves lots of shifting and rearranging of symbols, and if
967there is more than one X in the equation it can get into some rather
968complicated algorithms.
969
970Instead, this program compares the LHS and RHS values directly. (The
971difference between the LHS and RHS is the "lhs/rhs diff", and varies
972from the "delta"). This leads to several problems. Sometimes two sides
973of the equation form a really good match only because both sides
974involve something raised to a very small power (or a very big root --
975same thing). An example of this type of problem is 1.017262042 =
976[49sv] (the 81st root of 4) and 1.017313996 = [38sv] (the 64th root of
9773). They differ by only 1 part in 20000, but only because both numbers
978are very close to 1. All 81st and 64th roots of small integers are
979close to 1. This is referred to as the "error margin problem" (or
980"loss of significance").
981
982There is also the problem of zero subexpressions and constant
983subexpressions involving X. An example is "x1el-^ = 42sL": The
984subexpression "1el-" is "1-ln(e)" which evaluates to 0, and the entire
985LHS is x^(1-ln(e))" which will always be 1. The right-hand side (log
986base 2^2 of 4) is also 1, so this equation works for any X. In order
987for the program to work, such "solutions" have to be detected and
988eliminated. This is the "tautology problem".
989
990Finally, there is the issue of reporting what X would perfectly solve
991each equation. This is a desirable feature of the program because
992users will often want to find out what the "exact" value would be for
993a given equation without actually doing the algebra and calculations
994themselves. In cases like [xle+q] = [1e-s], where there is only one X
995in the equation, this could be done by the computer. However, there are
996lots of important cases like [xx^] = [52*] where an analytic solution
997does not exist and the value of X has to be found by some other method,
998such as a numeric method. This is the "root-finding problem"
999
1000Conveniently, all three problems (the error-margin problem, the
1001tautology problem, and the root-finding problem) are handled in the
1002same way: by calculating the *derivative* of all terms and
1003subexpressions on the LHS. The derivative, when multiplied by the
1004lhs/rhs diff, gives a very good approximation to the delta, which as
1005mentioned above is the amount that X would need to be changed to make
1006the equation a perfect match.
1007
1008This solves the error margin problem because it equalizes the field --
1009all equations can get rated in terms of how much X has to change to
1010make LHS and RHS match, rather than how much the LHS would have to change.
1011
1012It solves the tautology problem because, by definition, an LHS with
1013a zero derivative is constant with respect to X, and therefore
1014constitutes a tautology solution.
1015
1016It also solves the root-finding problem quite conveniently. If you have
1017an equation like X^X = 10, and you have an approximation for X, you can
1018use derivatives and Newton's method to find a better approximation for
1019X. When RIES takes the derivative of the LHS and multiplies it by the
1020lhs/rhs diff, it is essentially performing one step of Newton's method.
1021The resulting value can be added to X to form a better approximation to
1022the root of the equation.
1023
1024Derivatives are evaluated for LHS expressions as the expressions are
1025generated. In the following table, the calculation of the derivative
1026for each symbol is shown, based on the values of the operands (A and
1027B) and their derivatives (da and db). Some of these will be familiar
1028to anyone who has taken calculus:
1029
1030 seft '0' symbols:
1031 ' ' no-op
1032
1033 (other sefts will go here: roll, drop, dup, over, etc.)
1034
1035 seft 'a' symbols:
1036 3 any constant 0
1037 x target 1
1038 seft 'b' symbols:
1039 e exponential e^A da
1040 l natural log da / A
1041 n negate - da
1042 s squared 2 A da
1043 q square root da / 2 sqrt(A)
1044 r reciprocal - da / A^2
1045 A arctangent da / (1+A^2)
1046 C cosine -sin(A) da
1047 G Gamma %%% reserved (mutex with !)
1048 ! factorial %%% reserved (mutex with G)
1049 S sine cos(A) da
1050 T tangent (1 + tan^2(A)) da
1051 W LambertW W(a)/(a(1+W(a))) da
1052 seft 'c' symbols:
1053 + plus da + db
1054 - minus da - db
1055 * times A db + B da (note "product rule" below)
1056 / divide B da - A db / B^2 (note "quotient rule" below)
1057 ^ power A^B (ln(A) db + B da / A)
1058 v Bth root BvA (da / A B - db ln(A) / B^2)
1059 L log base B (da / A ln B) - (ln A / ln B) (db / B ln B)
1060 # paste digits %%% reserved
1061
1062 product rule d/dx f(x) g(x) = df g(x) + dg f(x)
1063 quotient rule d/dx f(x)/g(x) = (df g(x) - dg f(x)) / g(x)^2
1064 chain rule d/dx f(g(x)) = df/dg dg/dx
1065
1066 An example of applying the above to derive the formula for the derivative
1067 of A^B (where A and B are both functions of x):
1068
1069 A^B = exp(ln(A) B)
1070 d/dx exp(Y) = exp(Y) dY
1071 d/dx ln(A) = 1/A da
1072 d/dx ln(A) B = db ln(A) + B/A da (by "product rule")
1073 d/dx A^B = d/dx exp(ln(A) B)
1074 = exp(ln(A) B) d/dx (ln(A) B)
1075 = exp(ln(A) B) (db ln(A) + B/A da)
1076 = A^B (db ln(A) + da B / A)
1077 = A^B ln(A) db + B A^(B-1) da (standard form)
1078
1079 d/dx ln(A) / ln(B) = (ln(B) da / A - ln(A) db / B) / ln(B)^2
1080
1081 log(a+b) = log(a(1+b/a))
1082 = log(a) + log(1+b/a)
1083
1084 */ /*
1085
1086It is fairly easy to show that in any equation that constitutes a
1087solution, if any expressions or subexpressons evaluate to 0, the
1088entire equation can be replaced with an equivalent form that does not
1089involve 0. The equivalent form is never more complex and is usually
1090simpler. It can also be shown that any solution involving a
1091subexpression that contains x and has a 0 derivative can be reduced
1092to a simpler solution that does not.
1093
1094 Why RIES Calculates Derivatives
1095
1096Consider the value X = 2.5063. Each of the following solutions (or an
1097algebraic equivalent) will appear when you run RIES on it:
1098
1099 2 x = 5 for X = 2.5 *
1100 x^2 = 2 pi for X = 2.506628274631 *
1101 x^x = 1+9 for X = 2.5061841455888
1102 x^2+e = 9 for X = 2.5063356063267
1103
1104The exact solutions to these equations are all different values,
1105of course, and they all form successively closer approximations to
1106the supplied value 2.5063.
1107
1108*/ /*
1109
1110%%% the following description doesn't match the numbers; don't know
1111how to fix it...
1112
1113Look at the last two. Notice that the supplied value, 2.5063, is
1114between the exact solutions of these two. Also, the equations can both
1115be expressed in a different way:
1116
1117 2 X = 5 instead of X = 5/2
1118 X^2 = 2 pi instead of X = sqrt(2 pi)
1119
1120Consider what would have happened if the last digit had been one
1121higher or one smaller. How much does it change the "closeness" of the
1122match? With the original two equations, where there is just an "X" on
1123the left-hand side, this is easy to figure out: if X is 0.0001 lower,
1124it's 0.0001 closer fit for the first equation, and 0.0001 further from
1125the second. But look at the alternate forms: If you subtract 0.0001
1126from X, that subtracts 0.0002 from 2 X, but it subtracts 0.0005 from
1127X^2. That's a big difference -- if we're using these forms of the
1128equations (as RIES does) to determine how well the two sides match,
1129then this altered value of X makes the match "move" further with
1130respect to one equation than it does with respect to the other!
1131
1132The reason this happens is, of course, because we're looking at an
1133expresson on the left-hand side, rather than just a single "X".
1134Putting an expression on the left-hand side makes it harder to see how
1135close a match you've got.
1136
1137If you still don't believe this, consider 1.047246, and exclude sine
1138and cosine from the function set:
1139
1140<pre>
1141 ries 1.047246 -NSC
1142
1143 Your target value: T = 1.047246
1144
1145 3 x = pi for X = T - 4.84488e-05
1146 x^5 = 3 root-of 2 for X = T + 4.81228e-05
1147 1/ln(sqrt(x)) = 4^e for X = T + 1.77179e-05
1148 ...
1149</pre>
1150
1151We see that 1.047246 is an equally good solution for the following:
1152
1153 x = pi / 3 (too high by 0.00005)
1154 x = 15th root of 2 (too low by 0.00005)
1155
1156but if you express the solutions as the #ries# output does:
1157
1158 3 x = pi (3.14172, too high by 0.00013)
1159 x^5 = cuberoot(2) (1.25992, too low by 0.00029)
1160
1161suddenly it looks like the 3 x = pi solution is more than twice as
1162good. #ries# notices this and compensates for it regardless of the
1163form in which the equation is actually found. If you run RIES on the
1164value 1.047246 it will present both solutions, in the following form:
1165
1166 X * 3 = pi
1167 X ^ 5 = 3 v 2
1168
1169The philosophy adopted by RIES is that the "true" form for evaluating
1170the closeness of a match is the form where there is just one X, and
1171nothing else, on the left-hand-side of the equation, and just numbers
1172and symbols, but no X's, on the right-hand-side. (Let's call this the
1173"normalized form".) Put all equations into normalized form, calculate
1174the value on the right and look at the difference between X and this
1175value to determine how good the match is.
1176
1177But now go back to our 2.5063 example above -- one of its solutions
1178was:
1179
1180 X^X = 10
1181
1182This equation *cannot* be reduced to something with just one X on the
1183left-hand side -- there is no "inverse-of-X-to-the-X" function fn[1]. What
1184does RIES do?
1185
1186fnd[1] Actually, there is, but it uses an obscure function called the
1187"Lambert W function" which is the inverse of *y*=*xe^{x}*. More
1188details are [here|+numbers:xxy_root2] if you are interested.
1189
1190RIES calculates derivatives. By using the value of 2.5063 for X and
1191calculating the derivative of X^X for this value of X, you get (about)
119219. A derivative of 19 means that any small change in X will cause a
119319-times-bigger change in X^X. That's important, because it allows us
1194to compare the closeness of the match on "equal footing" with other,
1195normalized equations like X = sqrt(2 pi).
1196
1197Derivatives work so well, in fact, that RIES does not even have to
1198bother solving its equations for x. ven if it were easy to do this
1199(which it is not), leaving the equations unsolved is still an
1200important speed improvement. Part of the reason RIES is so fast is
1201that it generates left-hand-sides and right-hand-sides separately
1202(like a wl[Bidirectional_search] in graph theory) and tries all the
1203combinations to find possible solutions. It can do this a lot quicker
1204because a half-equation is smaller than a full equation, and therefore
1205there are less possibilities to check out.
1206
1207Furthermore, derivatives allow RIES to quickly and easily check a
1208possible equation to discover the value that X would have to be in
1209order to both sides to match exactly (it is essentially performing one
1210step of Newton's method).
1211
1212
1213
1214Examples of LHS and RHS expressions for the test case 2.5063. These
1215are shown in groups that correspond to the pairs that would actually
1216generate matches in a search:
1217
1218 expression value deriv.
1219 5/2 2.5 0
1220 hyprt(10) 2.506184 0
1221 x 2.5063 1.0
1222
1223 ,/25 5 0
1224 2 x 5.0126 2.0
1225
1226 x^2 6.281540 5.01
1227 2 pi 6.283185 0
1228
1229 x^2+e 8.999822 5.01
1230 9 9 0
1231
1232 9+1 10 0
1233 x^x 10.00222 19.19
1234
1235The derivative is based on the concept of an imagined error-bar in x
1236that is assumed to be small enough so that all reported matches are
1237relevant, but which is not zero. Thus, it is in units of the
1238infinitesimal quantity "epsilon".
1239
1240Let us now imagine that there is a constant "g" equal to (pi-1) *
12412.5063 ~= 5.367473. Then we would have the following grouping:
1242
1243 expression value deriv.
1244 pi^2-2 7.869604 0
1245 x+g 7.873774 1.0
1246 pi x 7.873774 3.14
1247
1248The matching "pi x = pi^2-2" constitutes a closer match than "x+g =
1249pi^2/2" because in the former case, x would only need to be decreased
1250by about 1/pi as much to make it an exact match. So, the closeness of
1251a match is measured as |LHS-RHS|/derivative, where smaller is better.
1252
1253To enable actual error bars to be provided with data, a value of
1254"epsilon" must be adopted for use with notionally precise supplied
1255values. This can be gleaned from the number of supplied digits in the
1256input, or the precision of the floating point format can be used. In
1257the latter case we would take the data value divided by 2 to the power
1258of the number of digits in the mantissa.
1259
1260 */ /*
1261
1262Future enhancements:
1263
1264 See "UNFINISHED WORK" section above
1265
1266 */ /*
1267
1268REVISION HISTORY
1269
1270 20000207 Begin (it does not do much except parse the parameters)
1271 20000208 Add parsing of level adjust and more design comments
1272 20000209 Write code to generate forms. "Discover" the Motzkin numbers.
1273 20000210 Optimize gf.1() by making it compute the stack depth as it
1274goes along rather than repeating the whole stack history on each test.
1275This improves time to generate all forms of length <=19 from 188
1276seconds down to to 37.9 seconds. Add tracking of min and max weights,
1277and start writing expression generator.
1278 20000215 It now generates forms within min and max possible
1279complexity limits, to avoid generating expressions from forms that
1280cannot possibly fall within the current complexity limit. Add a little
1281optimization; speeds up a deep search from 53 seconds to 37 seconds.
1282 20000217 It generates expressions, but doesn't prune for complexity
1283or evaluate. For the initial groups of 5, the numbers of expressions
1284evaluted are: {0, 12, 12, 72, 1368, 1368, 17928, 345672, 5875272,...}
1285 20000217 Prune for complexity limits; each expression is now
1286generated exactly once. The numbers are down to: {0, 1, 3, 18, 69,
1287182, 1046, 5358, 27123,...} Still need to prune foolishness like "11+"
1288and "nn".
1289 20000217 Prune almost all obvious trivial patterns. The numbers are
1290now down to {0,1,3,13,43,122,486,2186,9775,...}. Then prune [JK+] and
1291[JK-] for small integers, [jK*] and [jK+] for any j<K, and a couple
1292lesser things, and they're down to {...,43,106,391,1861,8608,...}.
1293
129420000217 Write metastack routines and exec(), and prune on eval errors
1295like divide-by-zero. This brings the numbers down to
1296{0,1,3,13,41,96,336,1605,7129,...}
1297
129820000217 Add using.x (formerly "on_rhs") variable and AM_RHS so it
1299generates LHS and RHS expressions, and make main outer loop call
1300gen_forms twice. In the LHS case there is lots of pruning. Figure out
1301that there is a substantial problem with error factors (derivative
1302of X) that will make lots of bogus "solutions" show up in the output.
1303
130420000218 Finish figuring out how to deal with the bogus solutions --
1305compute derivatives on all LHS expressions. This also solves the
1306"trivial solutions" problem (e.g. "x - x = ln(1)"
1307
130820000220 Add derivative calculation to exec() and the ms_xxx
1309routines. Initial output looks good, but I'm a bit worried about the
1310very high derivative values on things like [x8s^] -- they might
1311cause lots of bogus matches on things that aren't even close, like
1312"x8s^ = 6".
1313
131420000220 Add pruning of zero subexpressions, and of LHS expressions
1315with zero derivative. Examine output to check this; discover a bug
1316that ultimately turns out to be because I had ">> 2" instead of ">> 1"
1317in the s[] and ds[] declarations in struct metastack.
1318
131920000220 Refine the termination condition (now it counts generated
1320expressions, rather than cutting off at a certain complexity score --
1321this is to gain independence from the specifics of the weights) and
1322discover another dimensioning bug in struct metastack. Benchmark
1323changes in PASS_GRAN: When it is set to 4, 2, and 1 the execution time
1324for generating all expressions up to complexity 64 (2236462
1325expressions) is 3.57, 4.16, and 5.24 respectively. This actually a lot
1326better than I thought it would be -- I thought there would be a lot
1327more overhead from repeating the same subexpression evaluations over
1328and over again.
1329*/ /*
133020000220 Make it increase LHS and RHS complexity limits at independent
1331rates, such that the population remains equal between the two sides.
1332Add a bunch of comments documenting what's been done so far.
1333
133420000221 Write bt.insert(); it now reports exact matches! It finds,
1335for example, [x3+] = [4s] for X=13. However, for X=143 it reports
1336[xrx*] = [1], with a derivative of 1.9e-19. Add PRUNE_DERIV to try to
1337fix this, and it starts reporting [xxqL] = [2] with a derivative of
13380.00258248 -- this turns out to be a bug in the deriv formula for 'q'.
1339Eventually increase PRUNE_DERIV to around 1e-14, then decide to make
1340it a variable and add p_ovr and n_ovr. Write bt_prev() and bt_next(),
1341but not using them yet.
1342
134320000221 Figure out that I can check just the nearest LHS on either
1344side of an RHS, and vice versa. Write check.sides() and check.match.
1345It now finds answers and prints them out!
1346
134720000221 Fix bug in exact-match reporting. When given 1.5065916, it
1348reports:
1349
1350 match: [xe+s1+] = [p6*] (solution is X+5.14855e-08)
1351
1352Make it report delta you'd have to add to X to get each match to be
1353exact. Test cases that currently produce bogus results: 'ries -l1 27',
1354'ries -0.28676844', 'ries 403'
1355
135620000222 Adjust best.match by 0.999 each time to avoid long strings of
1357roundoff-error results. This fixes the './ries 403' case. Rename to
1358"ries" (it used to be called "misc"). Start analyzing memory usage.
1359Figure out how to save some memory in the node structures, and more
1360importantly, how to group nodes together in physical memory such that
1361the program degrades more gracefully when physical memory limits are
1362exceeded.
1363
136420000222 Implement -S and -O command-line options. This has the
1365side-effect of making certain bogus match bugs easier and quicker to
1366reproduce.
1367
136820000222 Change -S and -O to -N and -S respectively.
1369
137020000222 Convert manpage to #nroff# format. Improve implementation of
1371-S/-O/-N precedence. Implement -O option. Figure out why restricted
1372symbolsets create very small numbers of equations (the level controls
1373the number of expressions generated, which is always larger than the
1374number of expressions inserted in the tree)
1375
137620000222 Fix bug that caused negative X's to give no solutions -- it
1377was initializing best.match to a fraction of X, and not taking the
1378absolute value! Implement -i option so I can find an expression for
137970458.
1380
138120000223 Ignore -i if target is non-integer. Adjust weights for seft
1382'b' operators; 'l' now appears much less often in expressions. Add -y
1383option.
1384
138520000223 Write add.rule(); convert all AM_xx rules to add.rule()
1386calls. Now the AM_xx rules degrade gracefully with the symbolset
1387options. Change -y option to -x.
1388
138920000223 Clean up formatting in report.match(); add complexity score to
1390output. Write perl script to benchmark and take statistics on -i option
1391for a wide rance of integers; leave it running overnight. Change all 'int'
1392to 's16'.
1393*/ /*
139420000224 Today's date as a mathematical expression:
1395 (((4^(4^(1/e))-pi)^2)-pi)^2 the repetition is cool.
1396
139720000224 Write initial version of infix.1, then add a few rules
1398(ordering of bare symbols in '+' and '*'; always reverse order for 'v'
1399and 's'). Add -F option.
1400
140120000224 Add memory usage statistic.
1402
140320000225 Write infix.preproc; implement parentheses precedence.
1404
140520000225 Write eval() and newton(); printed X values are now (almost
1406always) exact roots of their equations. Add AM_1K rules.
1407
140820000226 Add copyright and GPL notices; add URL to first printf
1409
141020000226 Add symbol definition strings
1411
141220000227 Add sin and cos operators. Eliminate several bogus exact
1413match errors related to roundoff and loss of accuracy, e.g.
1414cosine(0.0001). Fix major bug in k_prune.deriv test: it only pruned
1415positive small derivs, not negative small derivs. Add symbol FORTH
1416names and write postfix.formatter (but it isn't used yet). Don't report
1417matches if newton() returned an error.
1418
141920000227 Add -ie variant to -i option (only_exact)
1420
142120000228 Kill another missing-fabs bug; remove prune on "almost exact
1422matches" which is now adequately covered by the derivative tests.
1423
142420000228 Add 'E' operator, AM_l and AM_E attributes, and PS_REVPOW.
1425check.match now uses newton() to evaluate score more accurately.
1426Add loss-of-significance test to '-' operator.
1427
142820000228 check.match calling newton was royally slowing things down.
1429Now it uses the old, much quicker test and then uses newton() as a
1430confirmation test. This cuts time for "ries 2.5063" from 4.09 down to
14311.39 on the Cyrix 180 (which is about what it has been since 0223).
1432Add statistics of pruned subexpressions ("dead-ends").
1433
143420000229 Fix bug in newton() that prevented success if target was
1435negative. Add debug printf's 'mnr'.
1436
143720000229 Add time display; add debug printf's 'opqsABCDEFG'.
1438
143920000229 Add debug printf's 'Hy' and a few notes about complex analytic
1440definitions
1441
144220000301 Change debug printf 's'; add another loss-of-significance test
1443to '+' and '-'; add debug printf's 'IJKLtuvx'. Add 'I' operator and
1444special-case tests for no defined symbols of each seft (this is a massive
1445optimization for "ries -ie 7 '-S1+*-/^v'")
1446
144720000302 Add debug printf 'w' and improve 'r'. Add arctan function (but
1448not using it yet) and some notes about derivatives.
1449
1450200003xx Benchmarks on a 333-MHz Celeron:
1451
1452 -command-------------------------- -mem- time equations
1453 ries 2.5063141592653589 960K 0.3 9.5619e7
1454 ries -l1 2.5063141592653589 3072K 1.5 1.0306e9
1455 ries -l2 2.5063141592653589 10.7M 6.5 1.2832e10
1456 ries -l3 2.5063141592653589 32.7M 24.4 1.2042e11
1457
1458200203xx Benchmarks on an 800-MHz PowerPC G4 (iMac, model M6498LL/A):
1459
1460 -command-------------------------- -mem- time equations
1461 ries 2.5063141592653589 960K 0.1 9.5062e7
1462 ries -l1 2.5063141592653589 3072K 0.8 1.0248e9
1463 ries -l2 2.5063141592653589 10.6M 3.6 1.2765e10
1464 ries -l3 2.5063141592653589 32.6M 14.3 1.1976e11
1465 ries -l4 2.5063141592653589 114M 70.3 1.4609e12
1466
146720020610 Figures from an unknown test (I can't find a record of the
1468details). I think the numbers are: memory usage; total
1469expressions/total distinct; total equations.
1470
1471 -l0 1136K 32198/14576 53165000
1472 -l1 2876K 145183/51492 666660000
1473 -l2 7632K 530668/152904 5712000000
1474 -l3 27100K 2311204/559419 78120000000
1475
1476200310xx Benchmarks on an 800-MHz PowerPC G4 (iBook G4, model M9164LL/A):
1477
1478 -command-------------------------- -mem- time equations
1479 ries 2.5063141592653589 960K 0.1 9.5062e7
1480 ries -l1 2.5063141592653589 3072K 0.7 1.0248e9
1481 ries -l2 2.5063141592653589 10.6M 3.2 1.2765e10
1482 ries -l3 2.5063141592653589 32.6M 12.8 1.1976e11
1483 ries -l4 2.5063141592653589 114M 62.3 1.4609e12
1484 ries -l5 2.5063141592653589 398M 388 1.7825e13
1485
148620050715 Benchmarks on a 2-GHz PowerPC G5 (part of a dual system,
1487model M9455LL/A):
1488
1489 -command-------------------------- -mem- time equations
1490 ries 2.5063141592653589 960K 0.0 9.5062e7
1491 ries -l1 2.5063141592653589 3072K 0.2 1.0248e9
1492 ries -l2 2.5063141592653589 10.6M 1.5 1.2765e10
1493 ries -l3 2.5063141592653589 32.6M 6.6 1.1976e11
1494 ries -l4 2.5063141592653589 114M 36.2 1.4609e12
1495 ries -l5 2.5063141592653589 398M 260 1.7825e13
1496 ries -l6 2.5063141592653589 1.41G 2183 2.2297e14
1497
149820070511 Alan Eliasen emails me to tell me that 'ries -l4 193707721'
1499gives the spurious result "x.(1/S(p))/x = 1/S(p) (exact match) {107}".
1500This is a problem I have known about for a while. I reproduce the
1501problem and reduce the symbol set to make it appear faster; it can be
1502reproduced with:
1503
1504 ries -F '-SxpSr/ *' -l0 1002353667
1505
1506Add rule ("",'S', AM_pi, 0), which eliminates "sin(pi)". It now reports
1507the following more complex version of the same bug:
1508
1509 x.(1/S(p.p/p))/x = 1/S(p.p/p) (exact match) {181}
1510
1511{This isn't actually a problem, it's doing what it should: When the
1512symbol '1' is not allowed, then "K/K" for any constant K *is* allowed.
1513However "ries -F '-SxpSr/ *1' -l1 1002353667" does produce the bug.
1514See 20090513 for fix. -20090513}
1515
151620090216 Clean up the comments, and add the "ARCHITECTURE" section,
1517plus a few notes on how to approach a multithreaded implementation.
1518 Here are the benchmarks from the 733 MHz Pentium 3 (from the manpage,
1519which I have now decided to update):
1520
1521 memory equations digits runtime
1522 usage tested matched (733MHz P3)
1523 -l0 960K 95,000,000 6+ 0.1 sec
1524 -l1 3.1M 1,030,000,000 7+ 0.7 sec
1525 -l2 11 M 12,800,000,000 8+ 3.3 sec
1526 -l3 33 M 120,000,000,000 9+ 12 sec
1527 -l4 115M 1,470,000,000,000 11+ 63 sec
1528
1529and here are the benchmarks from the 2.33-GHz Core 2 Duo (MacBook
1530Pro):
1531
1532 -command-------------------------- -mem- time equations
1533 ries 2.5063141592653589 960K 0.0 9.4018e7
1534 ries -l1 2.5063141592653589 3008K 0.1 1.0153e9
1535 ries -l2 2.5063141592653589 10.6M 0.6 1.2643e10
1536 ries -l3 2.5063141592653589 32.4M 2.7 1.1865e11
1537 ries -l4 2.5063141592653589 113M 13.6 1.4461e12
1538 ries -l5 2.5063141592653589 396M 81.7 1.7642e13
1539 ries -l6 2.5063141592653589 1.40G 651 2.2062e14
1540
154120090510 Add standard output format, and make it the default.
1542"-F" now takes a numeric argument (which formerly it did not)
1543and "-F" alone defaults to "-F0" which is what it did before.
1544{Formerly "F" was for "FORTH", and now it stands for "Format".}
1545 Future idea: A -W option to view weights (same as -S) or define
1546weights individually. --include could then be used to select weight
1547presets (e.g. a set of weights for electrical engineering). {This was
1548implemented on 20121209}
1549
155020090511 In infix modes, display operator 'L' (log base A of B)
1551in advance of both of its arguments. No longer put parens around
1552single-symbol argument of negate (e.g. emit "-x" instead of "-(x)").
1553
155420090513 Add rules to put bare 'x' after non-x-containing expressions
1555and bare 'pi', 'phi' and 'e'. Finish postfix.formatter (which had
1556never been brought into spec with the other formatters) and add it
1557as a 4th output option.
1558 As noted at 20070511, there has been a problem with expressions like
1559"pi*pi/pi". The command "ries '-SxpSr/ *1' -l1 1002353667 -F0" currently
1560shows the problem. I fix this by adding the three-symbol pattern AM_KxK
1561and the rule ("", '/', AM_KxK, 0).
1562
156320090515 "ries -l6 2.5063141592653589" running uncontested on the
15642.26-GHz Nehalem uses 1.40G of memory and tests 2.2154e14 equations in
1565442.4 seconds. Another test: 1.3525746932102463: 1.43G, 2.3011e14,
1566463.2. These times are 47% and 40% faster than the Core 2 Duo.
1567 Slight improvements to -Ds output. Improve rules for emitting "*",
1568" ", or "" for multiplication in different situations. Add rule
1569("12345678n", '-', AM_jK), and def_amkey/sym_amkey[] optimization.
1570
157120090808 Remove "val" parameter of my_alloc()
1572
1573*/ /*
1574
157520101218 Increase default level to -l2 (while preserving the effect
1576of all '-l' values when such an option is provided: "ries 1.234" is now
1577the same as "ries -l2 1.234", but "ries -l1 1.234" does the same thing
1578it used to do).
1579 Print 'x' instead of 'X'; use strcmp and strncmp in a few places.
1580
158120111216 Increase MAX_ELEN from 16 to 19 since we have room (struct
1582size is 64 in either case). Comment out unused obt_xxx declarations.
1583
158420111218 check.sides now checks more than one neighboring LHS if the
1585newly-inserted node is an RHS. Oddly, this does not cause more matches
1586to be reported, and I am not sure why.
1587
158820111219 print.end now displays max LHS and RHS complexity values; add
1589--find.expression option.
1590 Add k.vanished_dx and use it in several places to enforce a stricter
1591constraint on derivatives. This eliminates many of the more obscure
1592tautologies like "x^(4/ln(sqrt(x)))".
1593 Add --eval-expression option, and error numbers and error strings to
1594support it.
1595
159620111220 Restore ERR_EXEC_TRIG_LOW_DX error for RHS expressions;
1597restore legend in normal infix display format; eval() now reports
1598ERR_EVAL_TOO_LONG.
1599
160020111221 Slight improvements to postfix.formatter; report (most)
1601unrecognized or badly-formatted command options.
1602 Catch a few more tautologies by comparing magnitude of dx to
1603magnitude of x.
1604
160520111222 Add --version option.
1606
160720111223 -S without any symbols displays the symbol table and exits.
1608
160920111224 Enhance -Ds output by explicitly mentioning the Newton-Raphson
1610step.
1611
161220111226 Add loss-of-significance tests to each of the operators that
1613seem to need it: ln(x), e^x, sin, cos, +, -, a^b, a,/b, and log_a(b).
1614 Significance loss errors have always been easy to find in ries
1615output, by giving a target value that has a simple solution (like
1616"ries -1.4142135", which is used throughout this note). After ries
1617gives the simple solution (in this case "x^2 = 2"), subsequent
1618solutions can incorporate the simple solution in a
1619loss-of-significance tautology.
1620 The first of these solutions was {2012.0505: Now considered okay, now
1621that addition actually checks for loss of precision explicitly}
1622"1/(x+sqrt(2)) = e^(4^2) {86}". This incorporates the direct solution
1623into a tautology by turning "x^2=2" into "x+sqrt(2)=0", which isn't
1624exactly 0 because x is not exactly sqrt(2). Significance can be said
1625to be lost because many of the significant bits of the two terms "x"
1626and "sqrt(2)" cancel each other out in the addition. {2012.0505: In
1627this case, handled in exec() case '+', the loss of significance in
1628addition is easy to test rigorously: if (a+b)-b is equal to a, and
1629(a+b)-a is equal to b, then no information has in fact been lost.}
1630 This "x + -x" case is probably the most common source of significance
1631loss that I had not addressed until today. I fixed it by adding the
1632"fabs(rv) < (fabs(a) * k_sig_loss)" tests in exec() label
1633"add_common:"
1634 "ries -1.4142135" then gave "-ln(x^2-1) = 1/7^8 {109}" until I added
1635the k_sig_loss test in exec() case 'l'
1636 It then gave "-sin(pi x^2) = (1/5)^9 {111}" until I added the
1637k_sig_loss test in exec() case 'S'
1638 It then gave "log_2(x^2-1) = 1/-(e^(e^e)) {117}" until I added the
1639k_sig_loss test in exec() case 'L'
1640 Then it gave "1/(1/(x-1)-x) = (e^(4^2)),/2 {122}" until I added the
1641k_sig_loss test in exec() case 'v'
1642 It then gave "(x-1/(x+1))^2 = e^(1/(e^7)^2) {125}" until I added the
1643k_sig_loss test in exec() case 'E'
1644 After doing all of the above there was only one operator ('^') that
1645seemed to need a k_sig_loss test.
1646
164720111227 Change many details of formatting and printing to accomodate
1648the recent changes in handling of significant digits. Add constants
1649k_nominal_digits and k_usable_digits and associated format strings
1650fmt_g_xxx and use these in most places a floating-point value is
1651displayed. Redo the equation justify (space-padding) code to make the
1652best use of 80 columns while still showing centered equations and 15
1653significant digits when the -x option is given.
1654 Add init.numerics(); k_phi and k_pi are now computed from scratch.
1655 New 'z' option to -D and debug_z flag to show messages printed by
1656init.numerics().
1657
1658*/ /*
1659
166020111228
1661 Add more k_sig_loss tests in sin and cos.
1662 Display CPU time as "%.3f" rather than the old "%d.%d" that showed
1663seconds and tenths.
1664 RIES now exits when (best.match < k_0) regardless of the got.exact
1665flag; this fixes a bug that would cause RIES to loop forever if it had
1666not yet gotten an "exact match" at the point when best.match goes
1667negative.
1668 init.numerics() now computes k_e and detects the size of the ULP
1669(Unit in Last Place or "least significant bit").
1670 Add --min-match.distance option and g_min.matchsize to prevent
1671reporting of really close matches (useful in e.g. finding classical
1672approximation formulas for pi)
1673 Add --significance-loss-margin and k_sig_loss to allow going back
1674to RIES behaviour before all the new k_sig_loss tests were added.
1675 Share code by combining two exit tests into exact_exit() routine.
1676 ln(a) and log_a(b) functions now no longer reject a case like
1677ln(1.23e10) (in which only about 1 significant digit is lost)
1678 k_prune.deriv had been used for three different purposes, and now is
1679being replaced with three separate variables. The three purposes of
1680k_prune.deriv were:
1681 1. Detecting convergence in newton(). Now using new k_newton_settled
1682 2. Pruning subexpression tautologies in ge.2(). Now using k.vanished_dx
1683 3. Setting n_ovr and p_ovr in init2(). For now this is unchanged.
1684
168520111229 The big trig change: S and C now take units of pi radians, so
1686"3rS" now produces the value sin(pi/3)=0.866025... To support this I
1687also add the --trig-argument-scale option, which if given with the
1688parameter "1" gives the old trig units (radians). As a bonus, users
1689can now get degrees or grads or any other angle units.
1690 To avoid confusion, the trig functions are now called "sinpi" and
1691"cospi" in the output, unless --trig-argument-scale is set to
1692something other than pi; and the function definitions make this
1693obvious by adding a message like "For the trig functions, 360 units
1694are a full circle." at the end.
1695 While I'm at it, I add the tangent function 'T'. This had been in
1696the manual and in the symbolset since the start, but had not yet been
1697written in exec(). This of course makes a lot of things solve more
1698quickly, such as Gosper's "0.9674026381747" (the root of "tan(x) =
16993x/2", which previously needed a -l5 search, but with the unit change
1700and the tangent function, a -l0 search is sufficient.)
1701 One result of the trig units change is that there are a lot more
1702natural identities connecting common fractions and small radicals. For
1703example sqrt(2) is 2 sinpi(1/4), sqrt(3) is 2 sinpi(1/3), etc. This
1704makes ries generate and insert fewer expressions at a given complexity
1705level. It's so good in fact that you get higher complexity *and* less
1706memory usage even after adding the tangent function. Here are some
1707benchmarks, showing how much memory it used up and what level of
1708complexity it was able to achieve:
1709 --------old-------- --------new--------
1710 complexity complexity
1711 target-value LHS:RHS memory time LHS:RHS memory time
1712 1.5063 -l2 66:61 13632 KiB .319 66:62 12928 .342
1713 .328106566874978253 80:76 486848 KiB 39.5 81:76 461312 38.0
1714 1.9511889024071 80:76 494016 KiB 39.7 81:76 458432 37.8
1715 .922524879060934752 80:76 499264 KiB 40.4 80:77 464320 40.8
1716
1717(All except the first is at level -l5; the old figures were measured
1718using the options "--trig-argument-scale 1 -NT")
1719
172020111230 Add a pruning rule for [K+K-]->[] and pattern AM_KpK (which I noticed
1721after updating the sin(4)/cos(4)=1.1578212823 example from the manpage
1722and discovering that "ries 1.1578212823" prints "x+1-1 = tanpi(4/pi)".)
1723 Time measurement is now done by wall-clock time rather than CPU
1724cycle time. We do this with the gettimeofday() function. Formerly we
1725used getrusage(), which under-reports elapsed time on Nehalem and
1726later Intel microarchitectures when the core that we are running in
1727also has another thread running. This change also involved adding the
1728inittime() routine.
1729 Make several changes to facilitate porting this file to other systems:
1730 * #include <limits.h> and use LONG_MAX instead of __LONG_MAX__ (which
1731was a GCC-only predefined constant)
1732 * The symbol stack effect attribute (formerly called "class") is now
1733called "seft" (both in the comments and more importantly in variable
1734names) to facilitate porting to C++ (where "class" cannot be used as a
1735variable name because it is a language reserved keyword)
1736 * As mentioned above we now measure time with gettimeofday(); in
1737Windows we provide a gettimeofday() based on _ftime().
1738 * #include "stdafx.h" has been added before the other includes, to
1739facilitate Visual C++
1740 * #define RIES_VERSION ... has been moved to fall after the includes.
1741
174220111231 Add bt_first(), not yet used.
1743
174420120102 Increase k_min_best.match when fabs(target)>1.0, to avoid a
1745"search forever without exiting" condition that would always happen when
1746fabs(target)>16.0
1747 Add --include/-p (load profile) option, implemented in new routines:
1748file_read, delimit_args, and parse.args (which includes all the
1749argument-parsing formerly in main()).
1750 An included file contains options, delimited by blank space with
1751optional comments starting with '#'. Each non-blank non-comment
1752'token' is treated as if it were a string in argv[], with the strings
1753inserted into argv[] at the point where the settings-file option is
1754given, with recursion to support nested includes. Max 10MiB per file,
1755max recursion depth is 27 levels. This is to provide for all the fancy
1756new features I'd like to add someday (like user-defined symbol-weights
1757and functions).
1758 Add bt_depth and bt_stats (which is run by debug_y) to see if
1759rebalancing the binary tree will help. I conclude that it will not
1760help much: in a typical run the average tree depth with rebalancing
1761would be 17.5, and the actual (unbalanced) average depth is 24.5.
1762
176320120103 Add check.exact_match(), removing more RIES-specific code
1764from bt.insert.
1765 Add next_isparam(), clean up argument parsing and fix a bug with
1766parsing --significance-loss-margin argument.
1767
176820120104 Improve several of the debug_n printfs; add a bunch of
1769debug_q printfs to answer the question of why the check.sides change
1770of 20111218 did not produce more matches.
1771 Rename the old "on_rhs" variable to "using.x".
1772 Remove a lot of obsolete comments relating to an old idea for
1773maintaining two separate (LHS and RHS) lists. Update the comments on
1774derivative formulas and the Gamma function.
1775 check.sides now always checks only one expression to either side of
1776the newly-inserted expression. This causes a very few changes in
1777output, mainly in the first one or two reported matches. The reasons
1778are explained below in a block comment "THE CHECK_SIDES PARADOX".
1779 To support the check.sides investigation I added the -D0 option and
1780debug_0, which does a complete dump of the expressions database after
1781every gen_forms pass.
1782
178320120105 Add stack overflow and underflow checks in eval(). Increase
1784MAX_ELEN again to 21 (the expr struct is still 64 bytes).
1785 Add MAX_SEFT_POP checks in add.symbol().
1786 Add better documentation of the workings of the metastack routines.
1787 Implement canon.val() but leave it disabled by default right now.
1788This tries to transform expressions into forms that have a value in
1789[1.0,2.0), which also transforms expressions. For example, compare:
1790
1791 ries 1.50631415926535897932 --canon-reduction 0
1792 x-1 = 1/2 for x = T - 0.00631416 {50}
1793 1/ln(x) = sqrt(6) for x = T - 0.00213357 {62}
1794 x^4 = 2+pi for x = T - 0.000489459 {68}
1795 (x+1)^2 = 2 pi for x = T + 0.000314115 {69}
1796 x^pi = tanpi(sqrt(2)) for x = T - 0.000224565 {70}
1797 x^2 = tanpi(1/e) for x = T + 9.42083e-05 {60}
1798 x^2-2 = 1/(1+e) for x = T - 1.35846e-05 {79}
1799 1/(log_3(x)) = 3-1/pi for x = T + 8.87321e-06 {87}
1800 1/x+sqrt(2) = 1/ln(phi) for x = T - 2.77223e-06 {86}
1801 1/(log_7(x)) = 5-1/4 for x = T - 6.29902e-07 {94}
1802 . . . . . . . . .
1803 log_(2/sqrt(3))(x) = 3-1/2^e for x = T - 1.21748e-09 {128}
1804 max complexity: 66 62 128
1805 dead-ends: 2290352 5560466 7850818 CPU time: 0.369
1806 expressions: 183663 420208 603871
1807 distinct: 92770 113599 206369 Memory: 12928KiB
1808
1809 ries 1.50631415926535897932 --canon-reduction nr2
1810 x = 3/2 for x = T - 0.00631416 {48}
1811 (1/ln(x))/2 = sqrt(6)/2 for x = T - 0.00213357 {98}
1812 x^4/2 = (2+pi)/2 for x = T - 0.000489459 {104}
1813 (x+1)^2/2 = 2 pi/2 for x = T + 0.000314115 {105}
1814 -(x-4)/2 = pi,/2 for x = T - 5.21371e-05 {95}
1815 (1/(x^2-2))/2 = -(pi-5) for x = T + 2.16534e-05 {110}
1816 (1/(x^2-2))/2 = (1+e)/2 for x = T - 1.35846e-05 {115}
1817 e^(x-1) = (1/pi+3)/2 for x = T - 5.75694e-06 {101}
1818 1/(x/phi)^2 = 8,/pi for x = T + 7.44845e-07 {94}
1819 sqrt(3-x) = -tanpi(e-1) for x = T - 6.44308e-07 {101}
1820 (1/-(log_7(1/x)))/2 = (5-1/4)/2 for x = T - 6.29902e-07 {144}
1821 . . . . . . . . .
1822 sinpi(1/5),/x/2 = 1/-cospi(1/ln(sqrt(7))) for x = T + 1.15156e-10 {151}
1823 max complexity: 66 62 128
1824 dead-ends: 2290352 5560466 7850818 CPU time: 0.369
1825 expressions: 183663 420208 603871
1826 distinct: 63206 67234 130440 Memory: 8192KiB
1827
1828The intent is to get further with a given amount of memory by
1829collapsing equivalent equations like "x=-2" and "-x=2" into the same
1830solution. It succeeds in doing this, but also causes different matches
1831to be discovered and reported (despite the fact that the main loop is
1832still making the same choices about whether to call gen_forms on LHS
1833or on RHS). I need to investigate this further to discover why (one
1834possibility is that the new solutions come from things that would have
1835matched earlier, but didn't, because they lie in different places on
1836the number line and wouldn't meet up without needing more complexity).
1837
183820120107 -pfoo now tries opening "foo.ries" if "foo" cannot be opened.
1839 Add thrash_check() and related real-time memory allocation
1840benchmarking (not yet finished). This is based on ideas from a
1841discussion with Charles Greathouse yesterday.
1842
184320120108 More work on thrash_check(); add --min-memory option (which
1844presently does nothing, but eventually will prevent RIES from quitting
1845early in the event of unanticipated system slowness). Add --max.memory
1846option (which makes RIES definitely quit before exceeding a given
1847amount of memory).
1848
184920120113 Move nested functions out of parse.args() for compatibility
1850with non-GCC compilers.
1851 Presently, "ries 0.9674026381747 --eval-expression xp/T" shows a
1852different answer on different computers: I get "tanpi(x/pi) =
18531.4511039572620501" on MP16 and "tanpi(x/pi) = 1.4511039572620503" on
1854MBP. This causes commands, such as "ries 0.9674026381747 -l3", to
1855produce different results ("x/tanpi(x/pi) = 2/3" on MP16 and the
1856bizarre "x/tanpi(x/pi) = log_(sqrt(8))(2)" on MBP).
1857 I suspect a variation in the maths library routines under different
1858versions of MacOS. To fix this I probably need to bring in my own
1859tangent function. Sources for one version are in
1860"sun-trig-functions.txt". {This was addressed on 20121215, when I
1861added msal_math64.c and the RIES_USE_SA_M64 switch}
1862
186320120115 Add --memory-abort-threshold option and fix some segfaults
1864that were happening if the user does not give an expected option
1865argument.
1866 Add typedef sym_attr_block and use it for all the symbol table arrays.
1867
186820120121 Move all symbol tables into a single array of sym_attr_block
1869
187020120122 Add CANONVAL_MUL2 operation and stub cv.simplify() routine.
1871
187220120423 Notes on what I need to accomplish to finish canon.val,
1873decanon, and cv.simplify routines:
1874
1875 canon.val adds 'n', 'r', and/or '2/', '4/' to try to put an
1876 expression's value into the range [1, 2). Call it just before
1877 calling bt.insert. It should work on the existing expression
1878 structure and metastack state, and it needs to stop if MAX_ELEN is
1879 reached. We also need a decanon routine to undo its work before
1880 proceeding with the rest of ge.2.
1881 cv.simplify operates on two expressions (an equation), removing
1882 any unnecessary symbols that may have been added by canon.val. It
1883 takes two expressions A and B and removes any trailing '2/', '4/',
1884 'r' and 'n', or possibly shifts symbols from one expression to the
1885 other, all so as to make the equation A=B lower-complexity. Call
1886 this in check.match right after the initial test passes and before
1887 running newton() on the equation. This will most probably involve
1888 having two dedicated expression data structures so it (and newton(),
1889 etc.) will see our simplified equation rather than the two
1890 expressions that are actually in the database.
1891 The purpose of this is to conflate values like -2, -1, 1/2, 1, 2
1892 into a single tree entry, which should make more effective use of
1893 memory, at the expense of the output being a little less
1894 well-ordered by complexity-score.
1895 {These changes were begun on 20120514, but not finished until bug
1896 fixes on 20121210.}
1897
189820120425 RIES was used by Randall Munroe for XKCD #1047 (xkcd.com/1047)
1899{This led to changes allowing RIES to function as the back-end to an
1900online RIES server.}
1901
190220120428 Changes for UNIX and Windows compatibility (suggested by
1903Markus Milleder, via the xkcd forums).
1904 Also change Nth root symbol ',/' to '"/' because the '"' looks more
1905like the superscript 'n' that I use in the HTML for the ORIES server.
1906The server is mostly functional, at mrob.com/ries
1907
190820120503 Add --wide-output option (mainly for use by the ORIES
1909server). This is a 132-column version of the standard 80-column
1910output, adding two new columns. It displays the normal output plus the
1911-x version of the column showing equation roots, and a new column
1912showing the ratio (target/delta) in the form "1 part in 50" as in
1913xkcd.com/1047
1914
191520120505 There has been a bug for a while, causing "ries -l-2 -i 143"
1916to find the bizarre equation "(x-2)+3 = (3*4)^2" rather than the much
1917more obvious (and lower-complexity) "x+1 = (3*4)^2". This resulted
1918from sig-loss pruning and the k_sig_loss value 0.01: Because 1 is less
1919than 143*k_sig_loss, RIES disallowed the addition x+1. Similarly,
1920"ries 7775" failed to find "x+1=6^5" or even an alternate like
1921"(x+9)-8=6^5" because it couldn't add 1 (or any integer) to an x that
1922large.
1923 As a "narrow, conservative" fix, I have altered exec() case '+' to
1924attempt "(x+1)-1" and see if it is precisely equal to x. If so, then
1925we can assert that no significance loss has actually occurred
1926 Also add parse_target() to support future --mad option.
1927
192820120508 Numerous small changes to avoid warnings about sign mismatch
1929and using 'char' as an array index. Also add functions sym.strsym and
1930sym.strcmp.
1931
193220120509 Add --max.match-distance option, bringing it a bit closer to
1933supporting --mad.
1934
193520120510 Add the symbol ' ' which does nothing, so that --eval-expression
1936expressions can be formatted with whitespace if desired.
1937 Display a "still looking..." message if no results have been reported
1938after the first 2 seconds.
1939
194020120511 Add --numeric.anagram option and get it basically working. It
1941still needs a lot of testing, and the loop exit condition based on
1942search level needs a lot of work.
1943
194420120514 A bunch of little changes to fix compiler warnings.
1945
194620120515 Handle the gen_total / searchmax limits differently for
1947unidirectional searches like that done by --numeric.anagram. Prior to
1948this change, "ries -i 143 --numeric.anagram 143" would search forever
1949and finds nothing.
1950
195120120516 Add pf_float_wid; prune_count etc. are now doubles. Main loop
1952termination tests are now more flexible and general-purpose (important
1953for --numeric.anagram and other restricted searches).
1954
195520120518 Eliminate use of "s64" (long long 64-bit int) and associated
1956header files; I can use double instead for my large integers. Clean up
1957some size_t and char * typecasting. This is all for compatibility with
1958non-GCC compilers.
1959
196020120520 More cleanup, thanks to suggestions by Markus Milleder.
1961
196220120522 Add boolean datatype; eliminate all uses of explicit 32-bit
1963integers; add validate_types() and smarter detection/definition of s16.
1964
196520120613 Add --derivative.margin option. Also test different values of
1966the initial k.vanished_dx setting, and discover that it's safe to use
1967a much lower value like 1e-10. It's possible that most of the problems
1968fixed on 20111219 were also fixed by the sig_loss tests added later
1969in 201112; I'll have to do a lot of testing to be sure.
1970
197120120720 Add --one-sided option; --numeric.anagram now implies
1972--one-sided.
1973
197420120725 Change first argument of sym.strsym() from 'expr' to 'exp1' to
1975avoid namespace conflict with typedef 'expr'
1976
1977*/ /*
1978
197920121202 Better implementation of "--max.match-distance 0"
1980 Implement the --match.all-digits option, which makes RIES work more
1981like ISC. The capabilities has already been implemented, primarily in
1982parse.target(), the --max.match-distance option, and the "Still
1983searching" message in the main loop.
1984
198520121205 If the target value is large in magnitude, automatically set
1986k_vanished.dx as if the --derivative.margin option was given.
1987
198820121206 Add several formatting routines (symstrncpy0, sym.strncat,
1989endstack, expr_break, expr_print_infix, eqn_print_infix) and
1990try.solve() to implement the --try-solve-for-x option.
1991 This is in a rather rough state, as exemplified by the command "ries
19920.8183431428522 --try-solve-for-x", which will happily report "x =
1993sqrt(phi+pi)+3". I can fix that within try.solve() by calling eval()
1994after taking the square root of both sides to see if the LHS
1995is negative, and if so, append [n] to the RHS.
1996
199720121207 Fix the square root sign problem with 0.8183431428522, and
1998add some notes to try.solve.
1999 Increase NEWTON_MAX_ITER, and add notes about chaotic oscillation:
2000
2001 2012.1207: "ries 0.2322795271987 -l0" does not find "sinpi(x) = 2/3"
2002 because Newton does not converge: sin(x) in that region causes a
2003 divergent oscillation. "ries 0.23227952719876987" works because it
2004 happens to hit on an exact match, which thus does attempt to call
2005 newton(). The oscillation can be seen by passing -Dn: RIES is clearly
2006 trying all sorts of equations involving trig functions like [xS],
2007 [x2-T], etc. I could "fix" this by making the Newton iteration only go
2008 halfway to the next point each time:
2009 curr = curr + 0.5 * ((rhs_val - lhs_val) / (lhs_dx - rhs_dx));
2010 and increasing NEWTON_MAX_ITER to about 100, but that also introduces
2011 bogus solutions like "tanpi(-x) = 7^2" that I might not want. It's
2012 clear that trig functions in x are being rejected fairly often and if
2013 I change this behaviour, it will change a lot of RIES output.
2014
201520121208 Fix derivative formula for sine (case 'S' in exec()). It
2016has been wrong ever since I added --trig-argument-scale, and was
2017causing newton() to not converge in many (if not most) cases.
2018
201920121209 Add period-2 loop detection in newton(); this might allow
2020eliminating k_newton_settled later.
2021 Add sym.strlen, sym.strtrail, bothtrail and sym.strclip and begin
2022implementing cv.simplify.
2023 debug_p replaces debug_q for the "first score not good enough" case.
2024 new flag debug_e replaces debug_E; debug_E replaces debug_F.
2025 debug_F replaces canon.val cases of debug_G
2026 add new flag debug_Q for cv.simplify
2027 make debug_S and debug_s distinct variables (but 'S' and 's' debug
2028functions still print the same messages)
2029 Fix derivative formula for cosine.
2030 report.match now takes symstr arguments; copy expressions before
2031calling cv.simplify (which fixes heisenbugs that were caused by it
2032modifying the expression strings in the actual database nodes).
2033 Add a couple more rules to infix.preproc to improve --canon-reduction
2034output.
2035 new flag debug_N replaces debug_o.
2036 debug_o replaces debug_p (including the debug_q case changed earlier today).
2037 debug_p is now used by infix.preproc
2038 debug_F and debug_f are now distinct (canon.val for LHS and RHS respectively)
2039 Fix derivative formula for tangent and increase its symbol weight to 6
2040(sine and cosine are both 3)
2041 Add --symbol.weights option. A few simple tests like "ries 2.5063
2042--symbol-weights 1:T" quickly reveal that these "Gosper pi-scaled"
2043trig functions allow for pathological matches like
2044"tanpi(tanpi(tanpi(tanpi(1/tanpi(tanpi(ln(x))))))) = 1/3" mainly
2045because of the way the derivative scales up with each nested call of a
2046trig function. Al address this, I limit the ranges of sin, cos and tan
2047to +-pi (after applying the scale factor). Of course you don't want to
2048reduce symbol weights so drastically, and more realistic weight
2049adjustments (like "ries 2.5063 --symbol-weights 8:T") are more useful.
2050 Due to the argument syntax you cannot set a negative weight, and
2051large weight values automatically disable the symbol.
2052 Currently, The automatic setting of k.vanished_dx for large values
2053causes tautology errors when RIES is given large values. For example,
2054currently "ries -l3 1234567890" gives "x^2-sqrt(x)^4 = 2^8"
2055
205620121210 Pass parameters using_x, a_minw, a_maxw, etc. through the
2057recursive expression generation routines, rather than having them be
2058global variables.
2059 Add tautology warning messages when the target is very large or the
2060--derivative.margin is too small. Here are examples, in all cases using
2061a command like "ries -l4 4243743 --derivative.margin 2.0e-11", RIES
2062gives an answer like "x^2-sqrt(x)^4 = 1/-(2^8)"
2063 Target min. --d-m
2064 42437432.1 10.0e-9
2065 4243743.1 188e-11
2066 424374.1 11.8e-11
2067 112474.1 3.0e-11
2068
206920121211 Add a bunch of comments in ge.2(), etc.
2070 Add cv.simplify rule [Arr]=[B] -> [A]=[B]
2071
207220121212 Fix a bug in infix.1(): "7 times negative x" is now displayed
2073as "7*-x", before this fix it was "7 -x" which looks too much like
2074"7-x"..
2075
207620121214 Improve k_vanished.dx checks and error messages.
2077 It has been a while since I did benchmarks using the standard test
2078(2.506+pi/10^4 with no options), so I am going to run the benchmark
2079on all my machines again.
2080 Although I have been doing the same test since the beginning (see
2081above under the dates 200003xx, 200310xx, 20050715, 20090216 and
208220090515) the benchmarks are not directly comparable because of many
2083changes in the code. Improvements in error-checking, pruning rules,
2084the addition of the tangent function, and recent fixes to the
2085derivatives of trig functions have all affected the number of
2086generated expressions and therefore the running time and memory usage
2087for a given search level. (For details of all the changes, see above
2088under the dates 20101218, 20111219, 20111220, 20111221, 20111226,
208920111228, 20111229, 20111230, 20120505, 20120613, and 20121208). Here
2090is a representative sampling of statistics and running times from
2091"ries 2.5063141592653589 -l4" over the past few years:
2092
2093 Date and time expressions complexity time (Xeon
2094 YYYYMMDD.hh:mm LHS RHS LHS RHS equations memory E5520)
2095 20090217.02:36 1344958 1080143 76 70 1.453e12 155.3M 10.6s
2096 20090515.18:16 1344952 1080143 76 70 1.453e12 155.3M 10.5s
2097 20090516.01:13 1332922 1360355 76 71 1.813e12 172.4M 12.6s
2098 20111219.21:00 1332922 1360355 76 71 1.813e12 172.4M 12.2s
2099 20111220.23:28 1327806 1360355 76 71 1.806e12 172.1M 12.4s
2100 20111221.23:46 1327806 1360355 76 71 1.806e12 172.1M 12.3s
2101 20111226.18:27 1327757 1360355 76 71 1.806e12 172.1M 12.4s
2102 20111228.22:24 1251691 1280315 76 71 1.603e12 162.1M 11.60s
2103 20111230.06:26 1020295 1252891 76 72 1.278e12 145.5M 11.61s
2104 20120505.22:54 1032922 1281451 76 72 1.324e12 148.2M 11.55s
2105 20120613.23:35 1032922 1281451 76 72 1.324e12 148.2M 11.82s
2106 20121209.09:58 1032947 1281451 76 72 1.324e12 148.2M 11.80s
2107 20121210.07:24 930662 1127640 76 72 1.049e12 131.8M 10.74s
2108
2109Here are the current times for each level from -l0 to -l6, on all
2110machines back to the 800 MHz G4 (which is 10 years old).
2111
2112 PowerPC PowerPC Core 2 Xeon Core i7
2113 G4* G5* Duo E5520& 2720QM#
2114 Level -mem- eqns. 800 MHz 2.0GHz 2.23GHz 2.27Ghz 2.20GHz
2115 -l0 1.11Mb 6.89e7 0.333s 0.085s 0.035s 0.026s 0.022s
2116 -l1 3.47Mb 7.18e8 0.954s 0.304s 0.125s 0.102s 0.077s
2117 -l2 11.9Mb 8.46e9 3.495s 1.245s 0.518s 0.436s 0.364s
2118 -l3 39.3Mb 9.23e10 14.70s 6.407s 2.724s 2.125s 1.507s
2119 -l4 131 Mb 1.04e12 69.29s 34.13s 12.75s 10.70s 7.760s
2120 -l5 441 Mb 1.19e13 % 165.0s 64.15s 51.59s 38.29s
2121 -l6 1.51Gb 1.39e14 794.0s 322.2s 252.3s 190.1s
2122
2123 * For the G4 and G5 I was using a 32-bit binary, so the memory usage
2124 was a bit smaller.
2125 % The G4 did not have enough memory to run the -l5 or -l6 tests.
2126 & The Xeon E5520 has a base speed of 2.27Ghz, but during these tests
2127 all cores were otherwise idle, so it was running near its single-core
2128 turbo speed of 2.53 GHz.
2129 # The i7-2720QM has a base speed of 2.2 GHz, and all cores were otherwise
2130 idle during these tests. However, its turbo frequency depends on the
2131 amount of recent activity. Each test was run after the CPU had been
2132 completely idle for 1 minute. For tests under 25 seconds, this means
2133 the clock speed was near the maximum 3.3 GHz.
2134
2135*/ /*
2136
213720121215 Standalone math source (msal_math64.c) now includes SIN and
2138COS functions.
2139
214020121216 Fix a simple bug in symstrcmp that prevented
2141--find.expression from working.
2142
214320121217 Add --explicit-multiply option.
2144
214520121218 Allocate twice as much space for the RHS part of the equation in
2146try.solve and in report.match
2147
214820121223 Slight optimization inside the next symbol test loop of ge.2.
2149 Fix a few compilation warnings (missing prototypes; mismatched
2150integer types in some debug printfs)
2151
215220130121 Fix bug in -S option when used with --numeric.anagram (that
2153made it act as though the -S option had not been given).
2154
215520130127 While working on a simple Perl script to generate OEIS sequence
2156A005245 I discovered that the command:
2157
2158 ries --one-sided -ie -S1+* 23 -l5
2159
2160does not find any answer. I suspect this is a bug in complexity limit
2161optimizations. {After investigation I figure out it's simply that
2162MAX_ELEN is too low.}
2163
216420130129 Do a thorough inspection of all places where I check
2165expression lengths against MAX_ELEN and find a few places it can be
2166improved to make maximum use of the avaiable space. Allocate one more
2167symbol for certain expression scratch buffers. It should be able to
2168use all MAX_ELEN symbols now. Add RIES_MAX_EXPRESSION_LENGTH option, which
2169you can give when compiling RIES to make a RIES that handles longer
2170expressions.
2171 Make "exhaustion timeout" message suggestions more relevant;
2172don't show it at all if a result has been given; don't show "(for more
2173results, use the option '-l3')" suggestion if exhaustion timeout error
2174was given. Also add NO_IDENTITY_OPTIMIZATION code (currently disabled).
2175
217620130130 Add a 32-bit signed integer data type and corresponding
2177ifdefs and runtime sizeof testing. Symbol attributes mark is now 32
2178bits. Add rules for associative operators: for example, it now prunes
2179[ABC++] = A+(B+C) in favor of [AB+C+] = (A+B)+C.
2180
218120130201 Now using debug_B for the derivative prune messages formerly
2182displayed by debug_e and debug_E; re-use debug_E for "rejected
2183(duplicate value)"; debug_G now (properly) prints its message only
2184when an expression has actually been added, and uses infix notation
2185because -DG/-Dg may be useful to users who wish to use RIES to
2186generate a database of expressions for processing by another program.
2187
218820130203 Add Lambert W function define and test loop; then move the
2189test code to msal_math64.c. To see LambertW tests, compile with
2190RIES_USE_SA_M64 defined then invoke RIES with option -Dz.
2191
219220130218 "--max-match.distance 0" now causes RIES to exit if and when
2193it gets an 'exact' match. Add a roundoff-error disclaimer about
2194'exact' matches (unless -i was given).
2195
219620130228 Add null argument '-' (useful if you want to end a sequence
2197of arguments to something like --symbol.weights).
2198 -S, -O and -N now pre-empt each other in the order they are given
2199(which is necessary for users who combine different profiles).
2200 Add the -E option (replacing the old "or-mode" behavior of -S; this
2201will be necessary for future optional functions like A and W, and also
2202facilitates combining multiple profiles.
2203
220420130301 Change almost all occurrences of 'double' declarations to
2205one of
2206 ries_val: The value of an expression or subexpression
2207 ries_dif: The value of a derivative, error, uncertainty, the distance of
2208 a match, etc.
2209 stats_count: For counting generated expressions, equations, etc.
2210 time_flt: For measuring time and memory usage
2211 Add init.formats()
2212
221320130302 Move Gamma function code (now tested) to msal_math64.c. As
2214with LambertW (see 20130203) it is not yet available in expressions or
2215equations but you can see the internal tests of Gamma by compiing with
2216-DRIES_USE_SA_M64, then invoke RIES with the option -Dz.
2217 Add default --include/-p profile feature. It now looks in
2218getenv("HOME") or getenv("USERPROFILE") in Windows for either
2219"ries_profile.txt" or ".ries_profile" (either name works in all OS's).
2220This profile is loaded first before any of the other options; however
2221if you give no options RIES still prints the brief help and exits.
2222 Add a '-p' option that:
2223 - If given first, disables the default profile
2224 - If given anywhere else, loads the profile at that point (so you can
2225 give an option which is applied before loading the profile by
2226 e.g. "ries -p foo bar -p baz qux")
2227 Make the '--version' option display the path to the defaults file,
2228to aid field diagnostics.
2229
223020130303 Add attribute tags (TAG_INT, TAG_RAT, TAG_NONE) and implement
2231their calculation. This provides a more robust way to implement the -i
2232and -ie options, and more importantly it paves the way for new
2233features.
2234 Add --absolute-roots as synonym for -x; add --relative-roots option
2235(opposite of '-x').
2236 Use newly-added attribute tags to implement -i option (replacing
2237many calls to float() with hopefully less aggregate work; look in
2238exec() and search for 'g_restrict.subexpr'.)
2239
224020130305 Add --no-solve-for-x option (which merely undoes
2241--try-solve-for-x). Add setup_abc_mmw() as part of refactoring the
2242handling of restricted symbolsets.
2243
224420130306 Add --symbol.names option; this involves several changes to
2245how we define the symbols, all of which will help with future
2246improvements like user-defined constants.
2247
224820130307 '=' symbol can now be renamed. Add -r and -re options to
2249ensure that all solutions are rational when solved for x. (These are
2250just shorthand for using -N to exclude lots of symbols). Increase
2251allocation of temp buffers in infix_1, fixing a crash that happened
2252when using an all-seft-b symbolset and solving for x, e.g. "ries
22533.1415926535897932 -SeElq -s".
2254
225520130308 Add --no-refinement option, which causes it to never
2256decrease best.match, and therefore print *all* matches that do better
2257then the specified distance. This produces results similar to the ISC
2258(except still ordered roughly by increasing complexity) and may be
2259useful to folks (like the 137 cultists) who are happy with any formula
2260within a known error bound. It required adding sym.strneq,
2261symstrsymstr, unique.eqn and the g.matches memory block (none of which
2262are used unless you choose the option).
2263 Add the --max-matches option, 100 by default.
2264
226520130309 Add -n as a synonym for --max-matches, --integer-subexpressions
2266as a synonym for -i, and --rational-subexpressions as a synonym for -r.
2267
226820130310 Add the g_nr_deltas array to provide another type of pruning
2269for equivalent answers for --no-refinement.
2270 Add the "-c" (alias --constructible-subexpressions) option which is
2271similar to -r but also allows phi, square and square root. Do a little
2272refactoring of how the -D, -E, -i, -N, -O and -r options are handled.
2273 Begin refactoring the tags manipulation to use TYPE_xxx values: since
2274each attribute is a subset of another (e.g. the integers are a subset
2275of the rationals) I don't really need to use bit-fields.
2276
227720130311 Continued refactoring of tags, add TYPE_CONS and TYPE_ALG
2278tagging. Implement -a option; add tagname().
2279
228020130312 Add --rational-exponents option, which tests the tag of the
2281argument and generates the new error ERR_EXEC_ILLEGAL_EXPONENT; the
2282error is also generated if the argument contains x on the assumption
2283that the user probably does not believe x to be rational if he is
2284looking for an answer in the form of an algebraic number.
2285 Add --rational-trig-args option, which works similarly and also sets
2286k_sincos_arg_scale to pi; it generates the new error
2287ERR_EXEC_TRIG_ARGTYPE.
2288 Add -a (algebraic subexpressions) option, using these new restrict
2289options. To support this, the target number is automatically tagged
2290with the same type as the selected restriction (-r, -c, -a) unless it
2291is obviously an integer or half- or quarter-integer; if no restriction
2292option was given we tag x as transcendental. There are now four
2293classes of restrictions with easy command-line options: -i, -r, -c,
2294and -a.
2295 Add ":.:." syntax for defining a blank-space character in symbol
2296names.
2297
229820130314 Add --any-exponents and --any-trig-args options.
2299
230020130317 Compute rv_maxint and disallow -i when target is too large;
2301remove utf8-related code (obviated by --symbol.names)
2302
230320130318 Expand brief.help.
2304 Add "-l" option (without a numeric argument, i.e. a bare "-l" rather
2305than something like "-l3") to restrict answers to those that have
2306Liouvillian numbers as roots. With -l it finds that 1.632526919438153
2307is sqrt(2)^sqrt(2) and finds that 1.132997565885066 is a root of
2308x^5+x=3, but does not find that 2.31645495878561 is the root of x^x=7.
2309Along with the full unrestricted defaults, and the option "-Ox", this
2310makes for a rather full set of options to select popular classes of
2311numbers as the roots of the reported results.
2312
231320130219 Test g_restrict_exponents in functions 'l', 'E' and 'L'.
2314
231520130613 Add --no-slow-messages option; auto-set k_min_best.match and
2316k_vanished_dx for small targets.
2317
231820130626 Use "%Lg" in various debug printfs to support RIES_VAL_LDBL.
2319Add macros EXP, FABS, etc. and (ries_dif) typecasts in several places;
2320get long double precision pretty much working.
2321
232220130801 Initialize k_ulp sooner so it can be used by -ce
2323 --max-match-distance and --match-all-digits options now cancel each
2324other.
2325
232620130803 In --symbol-names, allow redefining a symbol to itself (e.g.
2327':^:^' when -F format is selected) by accepting space_sym definition
2328only once.
2329
233020130805 Benchmarks of standalone maths library vs. standard libm.
2331Using the command "time ./ries-libm 2.5063141592653589 -l5
2332--max-match-distance 1e-10", and SIMULTANEOUSLY running the same
2333command with the "ries-sa-math" library, the time is 0m45.373s with
2334the sa-math library and 0m45.568s using libm (the sa-math library is
2335actually faster).
2336
233720130809 Add ieee.paranoia()
2338
233920130810 Alphabetize the order of sections in parse_args()
2340
234120130811 Add ERR_EXEC_ILLEGAL_DERIV; exec() checks for overflow and
2342NaN in derivative calculations in several operators
2343 Print error and exit if target value is zero.
2344
234520130812 Pass root directly to report.match to get full precision in
2346the case where ries_val has much more precision than ries_dif.
2347Increase precision of calculations of pi and e in init.numerics. "long
2348double" now gives 31 usable digits on the PowerPC G5 (where GCC 4.0.1
2349and later provide double-double arithmetic), and show.version now
2350shows the architecture (PPC/Intel) and precision:
2351
2352 ries --version
2353 ries version of 2013 Aug 13, Copyright (C) 2000-2013 Robert P. Munafo
2354 architecture: PowerPC
2355 precision: long double (33 nominal, 31 usable)
2356 mathlib: standard
2357 profile: -p/Users/munafo/.ries_profile
2358 RIES is free software; see the source for copying conditions. There is NO
2359 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2360 Dual-G5 /Users/munafo
2361 : ries 2.50618 -x
2362
2363 Your target value: T = 2.50618 mrob.com/ries
2364
2365 x = 5/2 for x = 2.5 {50}
2366 x = e^3/8 for x = 2.510692115398458467616066206823 {67}
2367 x = sqrt(2*pi) for x = 2.506628274631000502415765284811 {55}
2368 x = x"/(1+9) for x = 2.506184145588769256292940922378 {70}
2369 x = pi^(ln(sqrt(6))^2) for x = 2.506182746702861729338863939787 {84}
2370 x = e^(5"/sqrt(3/7)) for x = 2.506182083318281693444031686493 {99}
2371 x = ln(pi*e+1+e) for x = 2.506180094504077068176274103417 {96}
2372 x = e^(log_(pi^2)(7))+1/6 for x = 2.506180001393763345666526465285 {107}
2373 x = sqrt(1/((1/e-ln(6))+sqrt(x)))
2374 for x = 2.506180000397503542091976573633 {118}
2375 (for more results, use the option '-l3')
2376
2377 log_A(B) = logarithm to base A of B = ln(B) / ln(A) sqrt(x) = square root
2378 e = base of natural logarithms, 2.71828... A"/B = Ath root of B
2379 ln(x) = natural logarithm or log base e pi = 3.14159...
2380
2381 --LHS-- --RHS-- -Total-
2382 max complexity: 67 62 129
2383 dead-ends: 2842183 5668638 8510821 Time: 2.106
2384 expressions: 198545 370110 568655
2385 distinct: 103576 107460 211036 Memory: 13248KiB
2386
2387 Total equations tested: 11130276960 (1.113e+10)
2388
2389By comparison, typical run time for the same command on PMG5 in double
2390precision is about 1.49, and memory usage is 10624KiB.
2391
239220130816 Add ries_strncpy, ries_intpow, ries_to_digits,
2393ries_snprinf_int, ries_strlen, ries_spfg, spfg and spff. Use these
2394in a few debug statments.
2395
239620130818 Remove trailing 0 digits from ries_spfg output (for example:
23972.50618e+12 instead of 2.50618000e+12); fix a few compilation
2398warnings.
2399
240020130820 Add ries_spfg_test and msal_test_spfg
2401
240220140226 Eliminate conversion to double in ries_to_digits, fixing an
2403'exponent adjust failed' error when trying to print values like 1.23e-789
2404
240520140227 Minor refactoring; add did_newton parameter to report_match
2406
240720140228 Add some logic to check.exact_match, duplicating some of the tests
2408done by check.match.
2409
241020140303 Generate ERR_EXEC_ZERO_DERIV error in '^', 'L' and 'v'
2411operations when the derivative calculation underflows to zero. This
2412eliminates several recently-reported tautology errors.
2413
241420140831 Expand brief_help() a little,
2415
241620141014 Add --min-equate-value and --max-equate-value options.
2417
241820141105 Add Lambert W function (duplicating and expanding on work by
2419Mark Shoulson).
2420
242120141106 Increase weight of 'tan' (that is, the tangent function when
2422--trig-argument-scale is not the default) to 6, bringing it in line with
2423'tanpi' (where the weight was always 6).
2424 Bug-fixes in Lambert derivative and error handling, in debug_z mode
2425call new test routine msal_test_lambertl
2426
242720141117 Make -i (integer subexpressions) more efficient by restricting
2428symbolset as is done for -r. All class restrictions now also exclude W.
2429
243020141122 RIES license is now GPL version 3 (formerly GPL v2). Reorder
2431the info in --version a little bit.
2432
243320141207 Add test of each subexpression against g_restrict.subexpr so
2434that if you do e.g. "-a -EL" the L will be enabled but effectively
2435ignored; however I also canonize the unofficially supported "-a -Ep"
2436by mutating the types of the predefined constants in a similar way as
2437was already done for the target value. This is how user-defined
2438constants without a user-defined class will need to be handled.
2439 Add --any-subexpressions to enable the old behaviour, e.g. the user
2440can use "-a --any-subexpressions -EL" to get the equivalent of the old
2441"-a -EL".
2442
244320141212 struct form now includes stk[] and arg1[], supporting rules
2444that check the first argument of binary operators; add one rule using
2445AM_a1_e.
2446
244720141213 Add AM_a1_1 rules; #qualify# tests show that several more
2448results are found in -l5 tests, indicating that these rules increase
2449pruning for deep searches.
2450
245120141216 Replace all "sprintf" with snprintf.
245220141217 Add #defines for most of the snprintf tempbuf sizes.
2453
245420160104 Enable cube root of a negative argument ("-9.8222414378011"
2455vector in qualify tests it)
2456
245720160131 Add mem_used_bytes for more precise reporting of how much
2458memory would be needed for small tasks; to support this I did some
2459signed-vs.-unsigned cleanup.
2460
246120160423 Finish re-indenting the big block of options tests in
2462parse.args()
2463
2464*/ /*
2465
2466BUGS and TO-DO
2467
2468 See "UNFINISHED WORK" section above
2469
2470THE CHECK_SIDES PARADOX
2471
2472The RIES algorithm maintains a single list of RHS and LHS expressions
2473sorted in numerical order. These are distributed pretty much randomly,
2474and when a new expression is added, RIES checks the preceding and following
2475list items to see if it can form an equation with the new item.
2476 The closeness of a match is the difference in values divided by the
2477derivative of the LHS:
2478
2479 closeness = |LHS(x)-RHS|/(d/dx LHS(x))
2480
2481If the new node is an LHS, then the values of LHS(x) and d/dx LHS(x)
2482are the same for every match-comparison that is made. One RHS in each
2483direction (upward and downward) is all that needs to be tested,
2484because any further RHS's will generate a larger value of
2485|LHS(x)-RHS|.
2486 However, when the new node is an RHS, the value of d/dx LHS(x) will
2487differ for each LHS that is found while scanning upward and downward
2488for candidate matches. Therefore, even after finding a new optimal
2489solution, the possibility exists that there might be another
2490even-closer optimal solution if you keep scanning further, coming from
2491an LHS that has a much lower value of d/dx LHS(x).
2492 Here is a concrete example. La and Lb are two LHS's with derivatives
2493of 1 and 10. Ra and Rb are two RHS's. They are shown here as if laid
2494out on a number line to make the example clearer. The nodes are
2495inserted in the order: La, Lb, Ra, Rb.
2496
2497 value: 1 2 3 4 5 6 7 8 9
2498 Ra Rb La Lb
2499 d/dx: - - 1 10
2500
2501When Ra is inserted, the match La=Ra is found, with closeness
2502(8-1)/1=7. Then Rb is inserted, and a new match La=Rb is found, with
2503closeness (8-7)/1=1. These are the only two matches it will report.
2504 However, the match Lb=Ra is has a closeness of (9-1)/10=0.8, which is
2505closer, and Lb=Rb has a closeness of (9-7)/10=0.2 which is closer
2506still. Lb=Ra should have been reported instead of La=Rb. The program
2507should report La=Ra, Lb=Ra, and Lb=Rb (in that order).
2508
2509For a real-life example, use the command:
2510
2511 ries .328106566874978253 -l-4 --trig-argument-scale 1 -NT -Dy0
2512
2513which only gives one result, "5 x = sqrt(e)". With -D0 it dumps the
2514entire table of values on each complexity pass. Look through this
2515output for the first occurrance of [xrS] and [9r] together:
2516
2517 28 xrS { 35} = 0.093664890868384448 , dx = 9.2481888991224963
2518 29 xp/ { 34} = 0.10443956395812863 , dx = 0.31830988618379069
2519 30 xs { 24} = 0.10765391922648457 , dx = 0.65621313374995649
2520 31 x3/ { 35} = 0.10936885562499275 , dx = 0.33333333333333331
2521 32 9r { 26} = 0.1111111111111111
2522 33 8r { 26} = 0.125
2523
2524The output shows that [9r] is inserted a few passes later than 'xrS',
2525so check.sides is looking at [9r]'s neighbors [x3/] and [8r].
2526 For a while in 201112 I made RIES look past the nearest neighbor,
2527and this command reported the result "sin(1/x) = 1/9". But as you can
2528see, sin(1/x) matches 1/9 more closely than x/pi, x^2, and x/3,
2529because the derivative of sin(1/x) is so much higher.
2530
2531This is an example of the above-described problem, and is the reason
2532why for a while RIES was checking multiple neighbors on each insert.
2533
2534The Paradox:
2535
2536Despite the foregoing, the present algorithm (in which check.sides
2537only looks at the one closest neighbor on both sides of a newly-added
2538expression) turns out to work very well.
2539
2540To understand why, look at the output of ries 1.506591651 -Dy0 and
2541find the first appearance of [1p6*-] :
2542
2543 448 x1+p^n { 56} = -17.937341258252982 , dx = -22.481451854903934
2544 449 1p6*- { 51} = -17.849555921538759
2545 450 xe+sn { 51} = -17.84955591743638 , dx = -8.4497469589180909
2546 451 xTe/ { 49} = -17.762306262640966 , dx = 857.98450178681276
2547 452 x7^n { 46} = -17.61849853924631 , dx = -81.859931782354067
2548
2549When [1p6*-] is inserted, the LHS expressions [xe+sn] and [xTe/] are
2550already present. [xTe/] has a much bigger derivative (over 100 times
2551as large), so it looks like a good candidate for a match that would be
2552missed if check.sides only looked at the first neighbor of [1p6*-].
2553
2554However, the distance in x values from [1p6*-] to [xTe/] is over 20
2555million times larger in magnitude than the distance from [1p6*-] to
2556[xe+sn], so the higher derivative of [eTe/] doesn't stand a chance.
2557
2558When checking for other similar cases, the same thing always happens:
2559when an RHS and LHS forms a new record close match, any other LHS's
2560in the area don't come anywhere close to being another new match.
2561
2562The reason for this is in the statistics. Going back to the
2563.328106566874978253 example, consider the range of values between 0
2564and 1. By the time there are 1000 expressions in this range, the
2565average distance between expressions will be about 0.001. However, the
2566distance between the two *closest* expressions will be much smaller,
2567somewhere on the order of e/10^-6.
2568 Now consider what happens when you insert another 1000 expressions
2569at random places in the range (0..1). There is a reasonably good
2570chance that one of these new 1000 points will come closer to an
2571existing point than any of the other old points was. This will be a
2572new match. However, the odds of having *another* new match at the same
2573time are very very low -- about 1 in 1000. In other words, in order
2574to get a situation where there are two good LHS matches near an RHS,
2575all three have to be within 10^-6 of each other.
2576
2577
2578 */
2579
2580/* stdafx.h (the precompiled header for Microsoft Visual C++) is included
2581 by "ries-for-windows.c", which then proceeds to include ries.c. The
2582 following intentionally generates an error in the event that someone
2583 tries to compile ries.c directly in Microsoft Developer Studio. */
2584#ifndef __GNUC__
2585# ifdef _WIN32
2586# ifndef RIES_USED_RFWC
2587// please_compile_ries_for_windows.c please_compile_ries_for_windows.c;
2588 /* INSTRUCTIONS FOR COMPILING RIES IN MICROSOFT DEVELOPER
2589 STUDIO (USING VISUAL C++) ARE PROVIDED IN THE SOURCE FILE
2590 "ries-for-windows.c" */
2591# endif
2592# endif
2593#endif
2594
2595/* %%% Incomplete: We need a three-stage algorithm: detect what is the
2596 precision of long double, check to see what they have requested, then
2597 decide which type of float to use, then actually declare things. */
2598#ifdef RIES_WANT_LDBL
2599# define RIES_VAL_LDBL
2600#endif
2601
2602/* If neither mathlib is selected, default to using the standard library
2603 provided by the compiler and runtime environment (as it is typically
2604 a few percent faster) */
2605#ifndef RIES_USE_SA_M64
2606# ifndef RIES_USE_STD_M64
2607# define RIES_USE_STD_M64
2608# endif
2609#endif
2610
2611/*
2612 We include <math.h> etc. first, because msal_math64 still uses part of
2613 the std math library, and its version info uses printf
2614 */
2615#include <math.h>
2616#include <stdio.h>
2617#include <stdlib.h>
2618#include <string.h>
2619
2620#ifdef RIES_USE_SA_M64
2621# include "msal_math64.c"
2622# ifdef RIES_VAL_LDBL
2623# define SIN(x) (msal_sinl((x)))
2624# define COS(x) (msal_cosl((x)))
2625# define TAN(x) (msal_tanl((x)))
2626# define LAMBERTW(x) (msal_lambertwl((x)))
2627# define GAMMA(x) (msal_lanczos_gamma((x)))
2628# else
2629# define SIN(x) (msal_sin((x)))
2630# define COS(x) (msal_cos((x)))
2631# define TAN(x) (msal_tan((x)))
2632# define LAMBERTW(x) (msal_lambertw((x)))
2633# define GAMMA(x) (msal_lanczos_gammal((x)))
2634# endif
2635#else
2636# ifdef RIES_VAL_LDBL
2637# define SIN(x) (sinl((x)))
2638# define COS(x) (cosl((x)))
2639# define TAN(x) (tanl((x)))
2640# else
2641# define SIN(x) (sin((x)))
2642# define COS(x) (cos((x)))
2643# define TAN(x) (tan((x)))
2644# endif
2645 /* You need to use the stand-alone library to get Lambert and Gamma. */
2646# define DUMMY_LAMBERT 1
2647# define LAMBERTW(x) (0.0)
2648# define GAMMA(x) (0.0)
2649#endif
2650
2651/* The following functions are acceptable as-is but need long double
2652variants. */
2653#ifdef RIES_VAL_LDBL
2654# define EXP(x) (expl((x)))
2655# define FABS(x) (fabsl((x)))
2656# define FLOOR(x) (floorl((x)))
2657# define LOG(x) (logl((x)))
2658# define LOG10(x) (log10l((x)))
2659# define POW(x,y) (powl((x),(y)))
2660# define SQRT(x) (sqrtl((x)))
2661#else
2662# define EXP(x) (exp((x)))
2663# define FABS(x) (fabs((x)))
2664# define FLOOR(x) (floor((x)))
2665# define LOG(x) (log((x)))
2666# define LOG10(x) (log10((x)))
2667# define POW(x,y) (pow((x),(y)))
2668# define SQRT(x) (sqrt((x)))
2669#endif
2670
2671/* ---------gettimeofday---------
2672 RIES uses gettimeofday() to measure how much time was used in the
2673 search. To port RIES to another OS, add another #ifdef case to
2674 provide another gettimeofday() function. */
2675#ifdef _WIN32
2676/* Windows version. Note that _WIN32 is defined even if building for a
2677 64-bit target (which in addition defines _WIN64) */
2678
2679/* <sys/timeb.h> and <sys/types.h> are needed for _ftime()
2680 http://msdn.microsoft.com/en-us/library/z54t9z5f(v=vs.71).aspx */
2681# include <sys/timeb.h>
2682# include <sys/types.h>
2683
2684/* <winsock.h> defines the UNIX-compatible "timeval" structure that we take
2685 as a parameter, allowing us to emulate the UNIX routine that RIES
2686 was designed to use. It's in winsock because network protocols use a lot
2687 of data structures that were originally defined by UNIX systems. */
2688# include <winsock.h>
2689
2690 /* from www.linuxjournal.com/article/5574 */
2691 void gettimeofday(struct timeval* t,void* timezone)
2692 {
2693 struct _timeb timebuffer;
2694 _ftime( &timebuffer );
2695 t->tv_sec=timebuffer.time;
2696 t->tv_usec=1000*timebuffer.millitm;
2697 }
2698
2699#else
2700/* On UNIX, Linux, MacOS X, and CygWin systems the gettimeofday function
2701 is in the standard libraries and is defined by these #includes. */
2702# include <sys/stat.h>
2703# include <sys/time.h>
2704#endif
2705
2706/* -------------- defines ------------------------------------------------- */
2707
2708#define RIES_VERSION "2016 Oct 08"
2709
2710/* Default search level. For backwards compatibility, the -l option adds
2711 a number to the DEFAULT_LEV_BASE value. Without a -l option, it acts as if
2712 -l was given with the parameter DEFAULT_LEV_ADJ. */
2713#define DEFAULT_LEV_BASE 2.0
2714#define DEFAULT_LEV_ADJ 2.0
2715
2716/* Maximum number of matches to output. Changed with --max-matches or -n */
2717#define DEFAULT_MAX_MATCHES 100
2718
2719/* Maximum length of a symbolic expression. NOTE: right now it's dimensioned
2720 to reflect a normal symbol set. However, in a run with a very limited
2721 symbol set the expressions grow in number a lot more slowly as the
2722 complexity score and length increase, and therefore a much higher MAX_ELEN
2723 would be necessary. The main problem is it affects the size of the
2724 list nodes, and therefore the memory footprint of the program. I guess
2725 I'll change it later, when I decide how to make the list nodes variable
2726 in size.
2727
2728 %%% It might be possible to fix this by a method similar to that used in
2729 rubik2. In the RIES case, we only add an expression to the tree when there
2730 is a single item on its FORTH stack, and there is no way to predict if or
2731 when a subexpression will ever have a stack depth of 1. However, we could
2732 add nodes to an auxiliary list when their MAX_ELEN space is full, then any
2733 expressions that come from them would have a predecessor pointer pointing
2734 back to the aux. item.
2735 For example, suppose ge.2 is at depth 16 and the current partial
2736 expression is ep2+3+4+5+6+7+8+. At this point there is no room to add more,
2737 and nothing has been put in the tree from this expression yet (except the
2738 initial "e"). So, we allocate a node that just contains "ep2+3+4+5+6+7+8+"
2739 and start reusing the MAX_ELEN space. Any nodes inserted into the LHS/RHS
2740 tree will have their "predecessor" pointer pointing back to the
2741 "ep2+3+4+5+6+7+8+" node, so that if they generate a match, the full
2742 subexpression can be reconstructed.
2743 */
2744#ifdef RIES_MAX_EXPRESSION_LENGTH
2745# define MAX_ELEN RIES_MAX_EXPRESSION_LENGTH
2746#else
2747# define MAX_ELEN 21
2748#endif
2749
2750/* EXPR_ALLOC gives enough space for the expression and a terminating null */
2751#define EXPR_ALLOC (MAX_ELEN+1)
2752
2753/* The size of the memory blocks we use */
2754#define ALLOC_SIZE 65536L /* %%% should be at least 8x the VM page size */
2755
2756/* This can be increased to improve speed, but it also decreases the
2757 efficiency of memory usage by having the balance of LHS's and RHS's be
2758 further from a 1:1 ratio. */
2759#define PASS_GRAN 1
2760
2761/* -------------- typedefs --------------------------------------------------
2762/
2763/ Our function validate_types() checks the sized integer types at runtime
2764/ and may instruct the user to recompile with -DSHORT_IS_S16, etc. so if
2765/ one of these is defined, we use it to explicitly define s16. */
2766#ifdef SHORT_IS_S16
2767 typedef short s16;
2768# define HAVE_S16
2769#elif INT_IS_S16
2770 typedef int s16;
2771# define HAVE_S16
2772#endif
2773
2774#ifdef INT_IS_S32
2775 typedef int s32;
2776# define HAVE_S32
2777#elif LONG_IS_S32
2778 typedef long s32;
2779# define HAVE_S32
2780#endif
2781
2782/* Without user override, we just guess. short has been 16-bit on virtually
2783/ all C compilers since about 1995, so it's a pretty safe guess.
2784/ {2012.0522: If we really wanted to glean the definition from the
2785/ environment, the cases I know of so far are:
2786/
2787/ Per the "stdint.h" in http://code.google.com/p/msinttypes/
2788/ Visual Studio 6 and Embedded VC++ 4 have a broken __int16
2789/ Use "#if (_MSC_VER < 1300)" and declare typedef signed short int16_t;
2790/
2791/ Per Markus Milleder, stdint.h is not available prior to 2010.
2792/ Use "#if (_MSC_VER < 1600)" to see if stdint is not yet provided
2793/ and declare typedef signed __int16 int16_t;
2794/
2795/ In 2010 (mirabile dictu) MSFT finally added stdint.h
2796/
2797/ In many other environments, but not all, stdint.h is available.
2798/ Various GCC flags might allow figuring out which is which. */
2799#ifndef HAVE_S16
2800 typedef signed short s16;
2801#endif
2802
2803#ifndef HAVE_S32
2804 typedef signed int s32;
2805#endif
2806
2807/* Similarly, these might be replaced by stdbool.h in the future. We would
2808/ need to use #ifdefs and #define overrides.
2809/ There are two possible issues:
2810/ * As with stdint.h, we need to provide for MSVC (see
2811/ stackoverflow.com/questions/8548521/ )
2812/ * Defining "true" to a specific numeric value (like "1"), or comparing a
2813/ booolean to a specific numeric value, causes failures:
2814/ b001 flag1, flag2;
2815/ flag1 = true; // Default option
2816/ flag2 = (argc > 2); // More than two arguments
2817/ ...
2818/ if (flag1 == flag2) // FAIL if comparing 1 to __INT_MIN__
2819/ Given that our definitions, the stdbool.h version, and old compilers'
2820/ implementations may differ, we check for boolean sanity in
2821/ validate_types(). */
2822typedef int b001;
2823#define B_FALSE (1==0)
2824#define B_TRUE (1==1)
2825
2826/* stats_count variables would be 64-bit integers, if it were easy to get
2827/ that across all platforms. Since RIES is designed to work on really old,
2828/ small systems (like a 50-MHz 486) we instead use double and a custom
2829/ "sprintf" function. The 53 bits given by IEEE 64-bit doubles is enough
2830/ for the statistics RIES keeps. */
2831typedef double stats_count;
2832
2833/* time_flt is a floating-point value used to hold a time measurement. */
2834typedef double time_flt;
2835
2836/* SYMBOL_RANGE is the dimension of an array capable of storing one of
2837 each possible value of typedef symbol. */
2838#define SYMBOL_RANGE 256
2839typedef unsigned char symbol;
2840
2841/* NOTE: %%% Although it looks like I am trying to maintain
2842 independence from having the symbol type be 'char', I actually have
2843 not accomplished this in the code. However, it won't be a total
2844 mess to convert it to 16-bit symbols or something like that, if
2845 someone decides that's necessary. The worst part will designing a
2846 new command-line syntax for specifying the symbolset for a search.
2847
2848 However, *BEWARE*! If you're increasing the symbol set
2849 significantly past its original level of about 40 symbols, the
2850 users will pay dearly in efficiency (runtime). Having a great
2851 variety of symbols will massively slow down the search. In
2852 particular, please resist the temptation to make one symbol for
2853 every integer (or even every prime number) from 1 to 1000, or some
2854 other arbitrary big number. There should not be more integer
2855 symbols than every other symbol combined! RIES is perfectly happy
2856 synthesizing the larger integers from the small ones on its own,
2857 just like it does for the fractions and irrationals.
2858
2859 If there's a problem with a search for "163.0" yielding "(x+2)/5 = 2^5+1"
2860 as an answer, the solution isn't to make "163" a symbol. Instead, look
2861 at ways to make RIES generate better-looking output by automatically
2862 printing the subexpression "2^5+1" as "33" and, when possble, simplify
2863 the equation by moving the other 5 to the RHS. The ability to
2864 show "163" expressed in terms of "two 2's, two 5's and a 1" is one of
2865 the reasons RIES was created. */
2866
2867/* phantom symbols */
2868#define PS_REVSUB 1 /* argument-reversed subtract */
2869#define PS_REVDIV 2 /* argument-reversed divide */
2870#define PS_cross 3 /* implied multiply (not used) */
2871#define PS_REVPOW 4 /* argument-reversed exponentiation */
2872#define IS_PHANTOM(x) (x < 10)
2873
2874/* A "ries_val" is a numeric value attained by performing calculations
2875 according to an postfix expression. ries_val's are created mainly
2876 by successive calls to exec(). */
2877#ifdef RIES_VAL_LDBL
2878 typedef long double ries_val;
2879# define RV_SS_FMT "%Lf"
2880#else
2881 typedef double ries_val;
2882# define RV_SS_FMT "%lf"
2883#endif
2884
2885/* A "ries_dif" is the value of a derivative with respect to x (as calculated
2886 within exec()), and can aldo be a measure of uncertainty or the difference
2887 between two candidate expressions when looking for a match. In all of
2888 these cases, full exponent range is needed but the mantissa/significand
2889 need not more precise than 3 or 4 decimal digits. */
2890typedef double ries_dif;
2891
2892/* Types of numbers. As the value increases, the labaling is more
2893restrictive: TYPE_RAT > TYPE_ALG because the rationals are a subset of
2894the algebraic numbers. */
2895#define TYPE_NONE 0 /* unknown, i.e. beyond the functions in RIES */
2896#define TYPE_TRAN 1 /* "transcendental": includes Gamma[pi], root of x^x=7 */
2897#define TYPE_ELEM 2 /* "elementary": algebraic with arbitrary exponents */
2898#define TYPE_ALG 3 /* Algebraic but not constructible */
2899#define TYPE_CONS 4 /* Constructible but not rational */
2900#define TYPE_RAT 5 /* Rational (but not integer) */
2901#define TYPE_INT 6 /* Integer */
2902#define TGMIN(a,b) (((a)<(b)) ? a : b)
2903typedef s16 ries_tgs; /* tgs-manip */
2904#define TAG_INT_P(tg) ((tg) == TYPE_INT)
2905#define TAG_RAT_P(tg) ((tg) >= TYPE_RAT)
2906
2907/* Other tags that might be useful in the future:
2908 - "blessed rational": This number is irrational, but has been tagged as
2909 valid for use in integer-only contexts at the expense of a higher
2910 complexity score
2911 - "blessed irrational": Similar, for irrationals
2912*/
2913
2914
2915/* this struct is used for expressions that have been inserted into
2916/ the binary tree. (LHS and RHS expressions are both put in the same tree) */
2917typedef struct expr {
2918 ries_val val; /* The expression's floating-point value */
2919 ries_dif der; /* The derivative (for LHS expressions only: if
2920 RHS, this will be 0.) */
2921 ries_tgs tags; /* The numerical attribute tags, e.g. TYPE_RAT */
2922 /* tgs-manip */
2923 struct expr *left; /* left child tree or 0 if none */
2924 struct expr *up; /* parent node, or 0 if we're the head */
2925 struct expr *right; /* right child tree or 0 if none */
2926 s16 elen; /* number of symbols in the expression, e.g. 8 */
2927 symbol sym[EXPR_ALLOC]; /* The expression in symbolic form, e.g. "p6*1-qe-"
2928 this field is last to allow for a possible
2929 future with variable length allocation */
2930} expr; /* 8+8+4+4+4+2+21+1=52 bytes, or 64 if using 64-bit pointers */
2931
2932/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2933 Obfuscated Binary Trees (An idea that seemed hackish at the time)
2934
2935A way to save memory on the RHS (constant subexpression) nodes. These
2936notes date back to a time when I considered maintaining separate trees
2937for LHS and RHS nodes.
2938
2939typedef struct rhs_node {
2940 ries_val val; // The expression's floating-point value
2941 void * P_L; // parent and left child pointers
2942 void * P_R; // parent and right child pointers
2943 symbol sym[EXPR_ALLOC]; // The expression in symbolic form, e.g.
2944 // "p6*1-qe-", null-terminated. This field
2945 // is last to allow for variable length
2946 // allocation in the future.
2947} rhs_node; // size: 8+4+4+12=28
2948
2949 P
2950
2951 P^L P^R
2952 L R
2953
2954The three links (parent, left-child and right-child) are XORed
2955together into the two fields P^R and P^L. As the tree is traversed,
2956the traversal routine always keeps track of what node it came from and
2957what that node's numeric value was. Then the three links are
2958reconstructed as follows:
2959
2960If the current node was reached by going down, we know P. L and R are
2961reconstructed by XORing P with the two fields P^R and P^L.
2962
2963If this node was reached by going up, we know either L or R. To find
2964out which one, we compare the val field of this node with that of the
2965node we just came from. If it's bigger, we came from the left child
2966and therefore, L is known. If it's smaller we came from the
2967right-child and R is known.
2968
2969If R is known, P is reconstructed by XORing R with P^R. Then L is
2970reconstructed by XORing P with P^L. If L is known, the same method is
2971used to get P and R.
2972
2973There is another, perhaps more direct way to save one pointer per node:
2974maintain a stack of parent pointers. As you descend, push parent pointers
2975on the stack, and pop them off as you ascend. However, it does not
2976appear that the methods can be combined to save two pointers per node:
2977if you descend, the node you arrive at has unknown L and R, both of
2978which would have to get reconstructed.
2979
2980typedef struct obt_traversal {
2981 s16 side; // LHS or RHS
2982 void * realnode; // points to actual LHS or RHS node (0 if we're
2983 // at the root)
2984 ries_val x; // The value
2985 ries_dif dx; // Derivative
2986 void * up; // Reconstructed parent pointer
2987 void * left; // Reconstructed left-child pointer
2988 void * right; // Reconstructed right-child pointer
2989 // If they want the expression, they can get it from *realnode
2990} obt_traversal;
2991
2992// %%% obt (which literally stands for "obfuscated binary tree")
2993// routines aren't written yet. {And probably never will be: I want to
2994// keep the option of going to a balanced binary tree, which will matter a
2995// lot if we need to partition the tree for efficient implementation of
2996// finite-use symbolsets as in --numeric.anagram. Rebalancing an OBT is
2997// just too much of a pain. -20120518}
2998
2999void obt_new(obt_traversal * it);
3000void obt_clone(obt_traversal * from, obt_traversal * to);
3001void obt_up(obt_traversal * it);
3002void obt_left(obt_traversal * it);
3003void obt_right(obt_traversal * it);
3004_____________________________________________________________________________*/
3005
3006/* M E T A S T A C K !
3007
3008 A metastack works like a stack of stacks. Imagine a normal stack
3009 with its push and pop operators. A metastack lets you treat the whole
3010 stack as an object being pushed and popped. Every time you do a push or
3011 pop, a copy of the *entire stack* gets pushed onto the metastack.
3012 Metastacks support a third operation, called "undo", which pops the
3013 previous version of the stack off of the metastack; this popped stack
3014 replaces the current stack. Thus, undo enables you to go "back in time",
3015 returning the stack to the state it was at some point in the past
3016 without having to remember what values were popped and pushed.
3017 This is useful in RIES's expression generator because it allows
3018 intermediate calculations to be reused from one expression to the next
3019 during the recursive scan, and upon backtracking the stacks from all
3020 earlier, shorter subexpressions are restored.
3021
3022To illustrate the workings of the metastack data structures and
3023explain why they are allocated as they are, we need to understand the
3024consequences of the choice of MAX_ELEN (which determines the maximum
3025number of symbols in an expression generated by ge.1 and ge.2).
3026 First, realize that gen_forms is designed to generate only those
3027forms that leave a single item on the stack at the end, and ge.1/ge.2
3028will comply with this. So the expression "234+" is "incomplete"
3029because it leaves two items on the stack. Also, "23++" would never be
3030generated even as a partial expression because it causes a stack
3031underflow.
3032 Odd and even differ:
3033 max expression sp
3034 length form expr max
3035 MAX_ELEN = 4:
3036 aabc 23s+ 2
3037 aacb 23+s 2
3038 abac 2s3+ 2
3039 abbb 2sss 1
3040 MAX_ELEN = 5:
3041 aaacc 234++ 3
3042 aabbc 23ss+ 2
3043 aacac 23+4+ 2
3044 aacbb 23+ss 2
3045 ababc 2s3s+ 2
3046 abbac 2ss3+ 2
3047 abbbb 2ssss 1
3048
3049 expr. operation emulated metastack data
3050 stack ---uv--- ---duv-- uvp -------ms------- msp --s-- -ds-- sp
3051 [] [] (empty) [ , , , ] [ , , , ] 0 [ , , , , , , , ] 0 [ , ] [ , ] 0
3052 [2] ms_push 2, [ , , , ] [ , , , ] 0 [v, , , , , , , ] 1 [2, ] [0, ] 1
3053 [23] ms_push 2,3, [ , , , ] [ , , , ] 0 [v,v, , , , , , ] 2 [2,3] [0,0] 2
3054 [23s] ms_pop 2, [3, , , ] [0, , , ] 1 [v,v,^, , , , , ] 3 [2, ] [0, ] 1
3055 ms_push 2,9, [3, , , ] [0, , , ] 1 [v,v,^,v, , , , ] 4 [2,9] [0,0] 2
3056 [23] ms_undo 2, [3, , , ] [0, , , ] 1 [v,v,^, , , , , ] 3 [2, ] [0, ] 1
3057 ms_undo 2,3, [ , , , ] [ , , , ] 0 [v,v, , , , , , ] 2 [2,3] [0,0] 2
3058 [23+] ms_pop 2, [3, , , ] [0, , , ] 1 [v,v,^, , , , , ] 3 [2, ] [0, ] 1
3059 ms_pop [] [3,2, , ] [0,0, , ] 2 [v,v,^,^, , , , ] 4 [ , ] [ , ] 0
3060 ms_push 5, [3,2, , ] [0,0, , ] 2 [v,v,^,^,v, , , ] 5 [5, ] [0, ] 1
3061 [23] ms_undo [] [3,2, , ] [0,0, , ] 2 [v,v,^,^, , , , ] 4 [ , ] [ , ] 0
3062 ms_undo 2, [3, , , ] [0, , , ] 1 [v,v,^, , , , , ] 3 [2, ] [0, ] 1
3063 ms_undo 2,3, [ , , , ] [ , , , ] 0 [v,v, , , , , , ] 2 [2,3] [0,0] 2
3064 */
3065#define MS_UV_MAX ((MAX_ELEN)-1)
3066#define MS_UNDO_MAX ((MAX_ELEN) * 2)
3067#define MS_STK_MAX (((MAX_ELEN)+1) >> 1)
3068typedef struct metastack {
3069 ries_val uv[MS_UV_MAX]; /* undo values */
3070 ries_dif udv[MS_UV_MAX];/* undo values (derivatives) */
3071 ries_tgs utg[MS_UV_MAX];/* undo values (tags) */
3072 s16 uvp; /* undo values pointer */
3073 s16 ms[MS_UNDO_MAX]; /* metastack (undo opcodes) */
3074 s16 msp; /* metastack pointer (undo opcodes index) */
3075 ries_val s[MS_STK_MAX]; /* current stack */
3076 ries_dif ds[MS_STK_MAX];/* stack of derivatives for LHS */
3077 ries_tgs tg[MS_STK_MAX];/* tags, e.g. integer or rational */
3078 s16 sp; /* stack pointer */
3079} metastack;
3080/* the metastack undo opcodes. If you wanted to support more than simple
3081 push and pop you would add another opcode for each operation (example:
3082 a modify-in-place operator, something which normally requires a pop
3083 followed by a push) */
3084#define MSO_PUSH 1
3085#define MSO_POP 2
3086
3087/* "pe" stands for "partial expression". This struct is used by the
3088 recursive expression generator. Typically about half of its symbols
3089 will be filled in, and the complexity of the symbols written so far is
3090 compered to rminw and rmaxw for pruning.
3091 Here's an example. Let's say the current weight limits are 30 to 31:
3092 we're trying to generate expressions whose total weight is either 30
3093 or 31. And suppose further that the partial expression currently contains
3094 two symbols with a total weight of 18. That means that the remaining
3095 symbols must add up to either 12 or 13 for the expression to be accepted.
3096 When it's generating expressions, RIES already knows what form (see
3097 below) the expression fits into, and therefore it knows how many symbols
3098 are left to generate and what types they are. Therefore, certain statements
3099 can be made about the weights of the symbols yet-to-be generated. Let's
3100 say the current form calls for two more symbols, both of type 'b', and
3101 suppose further that all 'b' symbols have weights of 8, 9 or 10. Well, that
3102 means that at this point in our example equation, even if the two remaining
3103 symbols are 8's, the total weight will be too high. Thus, the first two
3104 symbols form an impossible combination (from the point of view of trying
3105 to meet the current range of 30 to 31), and the expression generator
3106 can backtrack immediately, without having to proceed to explore all the
3107 combinations of two more type 'b' symbols that might be added here. That
3108 saves a LOT of time -- this optimization alone cuts the number of
3109 expressions by a factor of over 200 (for searches of 10,000,000 expressions)
3110 and even more if a larger number of expressions is searched.
3111*/
3112typedef struct pe {
3113 s16 cplx; /* complexity of this partial-expression */
3114 s16 elen; /* number of symbols, e.g. 2 */
3115 symbol sym[EXPR_ALLOC]; /* the symbols, e.g. "p6" */
3116 s16 pe_rminw[EXPR_ALLOC]; /* remaining minimum weight */
3117 s16 pe_rmaxw[EXPR_ALLOC]; /* remaining maximum weight */
3118} pe;
3119
3120/* A "form" is a pseudo-expression consisting only of A's, B's and C's. The
3121 A's, B's and C's represent the three types of symbols that make up
3122 real expressions. Before real expressions are generated, RIES first
3123 determines what sequences of type-A, type-B and type-C symbols will
3124 constitute legal expressions. (It's easier to describe what an illegal
3125 expression is: It's an expression that causes the stack to underflow
3126 by executing an operation without enough operands, or an expression
3127 that leaves extra stuff on the stack when it's done.) */
3128typedef struct form {
3129 s16 min_weight; /* min attainable complexity with this form */
3130 s16 max_weight; /* max attainable complexity with this form */
3131 s16 stack; /* stack depth at end of form */
3132 s16 flen; /* number of symbols in form */
3133 symbol sym[EXPR_ALLOC]; /* the form, e.g. "aabc" */
3134 s16 stk[EXPR_ALLOC]; /* stack height after applying this symbol */
3135 s16 arg1[EXPR_ALLOC]; /* ptr to first arg of any 'c' symbols in sym */
3136} form;
3137#define ARG1_NA -1
3138
3139typedef s32 attr_bits; /* Attribute bits for symbol rules */
3140
3141typedef struct sym_attr_block {
3142 symbol seft; /* the symbol's stack effect */
3143 s16 sa_wgt; /* for scoring */
3144 s16 preempt_weight;
3145 attr_bits sa_mask; /* Attributes, masked with this, must be 0 */
3146 s16 sa_alwd; /* Number of symbols allowed in each expression */
3147 s16 sa_ct; /* used in ge.2() to keep track of how many symbols
3148 are in expression; part of -O option. */
3149 const char * defn; /* symbol definition for legend */
3150 const char * desc; /* Used for -S (show symbolset) option */
3151 s16 def_given;
3152 s16 def_needed;
3153 const char * sa_name; /* The "normal" (infix ASCII) symbol name */
3154 const char * name_forth;/* The symbol's postfix (FORTH) name */
3155 attr_bits amkey; /* "easy" attributes */
3156 s16 sa_known;
3157} sym_attr_block;
3158
3159#define MAX_SYMBOL_WEIGHT 100.0
3160#define MIN_SYMBOL_WEIGHT 0.0
3161#define MAX_SYM_NAME_LEN 24
3162
3163s16 g_addsym_seq;
3164
3165/* -------------- variables ----------------------------------------------- */
3166
3167char * g_argv0; /* Set to argv[0] by main for use by sudden death errors */
3168
3169double g_levadj; /* -l option or default DEFAULT_LEV_ADJ */
3170
3171char *block_base; /* pointer to current alloc block */
3172char *freepool; /* ... and the beginning of the free portion therein */
3173size_t freesize; /* ... and # of bytes left in the free portion */
3174
3175expr *lhs_root; /* binary tree for LHS list */
3176/* expr *rhs_root; binary tree for RHS list (not currently used) */
3177
3178s16 lmax; /* current complexity maximum limit for LHS */
3179s16 rmax; /* current complexity maximum limit for RHS */
3180s16 lmin; /* current complexity minimum limit for LHS */
3181s16 rmin; /* current complexity minimum limit for RHS */
3182
3183double tlevel; /* The maximum level (depth) of the search. The search
3184 ends when LHS + RHS > tlevel */
3185
3186ries_val g_target; /* The value for which we are searching */
3187ries_tgs g_targ_tags; /* The tags for the target value */
3188ries_dif g_mag_ulp;/* Magnitude of one base-10 unit in the last place (ulp),
3189 used for --mad option */
3190ries_val exec_x; /* the value exec() uses for 'x' symbol (differs from
3191 g.target during Newton iteration) */
3192
3193b001 got_exact;
3194stats_count g_num_matches;
3195stats_count g_max_matches;
3196symbol * g_matches = 0;
3197size_t g_mtch_alloc = 0;
3198ries_val * g_nr_deltas = 0;
3199
3200sym_attr_block sym_attrs[SYMBOL_RANGE];
3201s16 weight_base; /* weight per symbol for expression
3202 complexity score */
3203b001 x_lhs_only; /* true if symbol 'x' should only be on
3204 LHS (this is not necessarily the same as
3205 "-Ox" because there can be multiple x's
3206 in an LHS) */
3207char * g_anagram = 0; /* A string of digits used for solving
3208 "four 4's" and similar problems. */
3209b001 g_no_cv_simplify;
3210b001 g_one_sided;
3211b001 g_solve_for_x;
3212#define LINELEFT_INIT (79-2)
3213
3214int used_trig; /* Set if any trig symbol has been used in
3215 a result */
3216
3217b001 S_option;
3218b001 NOS_options;
3219b001 g_show_ss;
3220b001 g_reported_exhaustion;
3221
3222ries_tgs g_restrict_subexpr; /* nonzero if they gave -i, -r or -c option */
3223
3224ries_tgs g_restrict_exponents; /* nonzero to limit exponents to being e.g. rational */
3225ries_tgs g_restrict_trig_args;
3226
3227b001 g_relative_x; /* true if X values should be given relative to T */
3228b001 g_wide_output; /* true if wide output mode is selected (perhaps
3229 a bitmask in the future, but not yet) */
3230b001 g_explicit_multiply; /* Always show '*' symbol for multiplication */
3231
3232/* attribute masks */
3233#define AM_KK 0x0001 /* K K - */
3234#define AM_1 0x0002 /* 1 - */
3235#define AM_2 0x0004 /* 2 - */
3236#define AM_n 0x0008 /* n - */
3237#define AM_r 0x0010 /* r - */
3238#define AM_55 0x0020 /* J K - where J and K are both 5 or less */
3239#define AM_jK 0x0040 /* J K - where J < K */
3240#define AM_RHS 0x0080 /* set only when filling RHS list */
3241#define AM_sq 0x0100 /* op - where op is 's' or 'q' */
3242#define AM_1K 0x0200 /* 1 K - */
3243#define AM_l 0x0400 /* l - */
3244#define AM_E 0x0800 /* E - */
3245#define AM_pi 0x1000 /* p - */
3246#define AM_KxK 0x2000 /* K * K - */
3247#define AM_KpK 0x4000 /* K + K - */
3248#define AM_plus 0x8000 /* + - */
3249#define AM_mul 0x10000 /* * - */
3250#define AM_pow 0x20000 /* ^ - */
3251#define AM_a1_e 0x40000 /* e <expr> <seft_c_op> */
3252#define AM_a1_1 0x80000 /* 1 <expr> <seft_c_op> */
3253#define AM_a1_r 0x100000 /* r <expr> <seft_c_op> */
3254
3255#define MAX_SEFT_POP 20
3256symbol g_asym[MAX_SEFT_POP]; /* the valid seft 'a' symbols */
3257s16 n_asym;
3258s16 g_a_minw; /* minimum weight of seft 'a' symbols */
3259s16 g_a_maxw; /* maximum weight of seft 'a' symbols */
3260
3261symbol g_bsym[MAX_SEFT_POP]; /* the valid seft 'b' symbols */
3262s16 n_bsym;
3263b001 g_used_identity;
3264s16 g_b_minw; /* minimum weight of seft 'b' symbols */
3265s16 g_b_maxw; /* maximum weight of seft 'b' symbols */
3266
3267symbol g_csym[MAX_SEFT_POP]; /* the valid seft 'c' symbols */
3268s16 n_csym;
3269s16 g_c_minw; /* minimum weight of seft 'c' symbols */
3270s16 g_c_maxw; /* maximum weight of seft 'c' symbols */
3271
3272s16 s_minw; /* minimum weight of any symbol */
3273
3274s16 g_exhaust_cpx; /* Maximum weight of an entire expression */
3275
3276s16 max_flen; /* max length of forms generated thus far */
3277
3278/* Irrational constants have lots-o-digits just in case this program ever
3279 gets ported to a C compiler that offers quad-precision floating point. */
3280ries_val k_0 = 0.0L;
3281ries_val k_ern = (ries_val)-0.367879441171442321595523770161460867445811L; /* -1/e */
3282ries_val k_1 = 1.0L;
3283ries_val k_phi = (ries_val)1.61803398874989484820458683436563811772030L;
3284ries_tgs tg_phi = TYPE_CONS;
3285ries_val k_2 = 2.0L;
3286ries_val k_e = (ries_val)2.71828182845904523536028747135266249775724L;
3287ries_tgs tg_e = TYPE_ELEM;
3288ries_val k_3 = 3.0L;
3289ries_val k_pi = (ries_val)3.14159265358979323846264338327950288419716L;
3290ries_tgs tg_pi = TYPE_ELEM;
3291ries_val k_4 = 4.0L;
3292ries_val k_5 = 5.0L;
3293ries_val k_6 = 6.0L;
3294ries_val k_7 = 7.0L;
3295ries_val k_8 = 8.0L;
3296ries_val k_9 = 9.0L;
3297
3298/* Constants that parametrize functions */
3299
3300ries_val k_sincos_arg_scale = 0;
3301b001 g_trig_scale_default;
3302
3303/* These constants are used to set legal limits in various functions */
3304ries_val k_sin_clip = (ries_val)0.99999L;
3305ries_val k_2pi = (ries_val)6.28318530717958647692528676655900576839433L;
3306ries_dif k_eXlim = 690.0;
3307ries_dif k_d_nan;
3308ries_dif k_d_inf;
3309ries_dif k_d_ninf;
3310
3311ries_dif k_precision_ulp = 0.0;
3312ries_dif k_min_best_match = 1.0e-15;
3313ries_dif k_max_match_dist = -0.01; /* Default is to scale by 0.01 of the target
3314 value */
3315ries_dif g_init_match_dist;
3316b001 g_match_all_digits = B_FALSE;
3317
3318ries_dif k_sig_loss = 0.01;
3319
3320#define DEFAULT_K_VANISHED_DX 1.0e-6
3321ries_dif k_vanished_dx = DEFAULT_K_VANISHED_DX;
3322ries_dif k_biggest_safe_target = 10.0 / DEFAULT_K_VANISHED_DX;
3323
3324ries_dif k_derivative_margin = 0;
3325ries_dif k_prune_deriv = 1.0e-10;
3326ries_dif k_newton_settled = 1.0e-15;
3327
3328ries_dif g_min_matchsize = 0;
3329b001 g_exact_exit = B_FALSE;
3330b001 g_refinement = B_TRUE;
3331
3332ries_dif p_ovr;
3333ries_dif n_ovr;
3334
3335ries_val g_min_equ_val = -9.9e99;
3336ries_val g_max_equ_val = 9.9e99;
3337
3338/* Format strings and precision constants.
3339
3340The binary formats, and associated precision/significance values, of the
3341floating-point types that one is likely to encounter are:
3342
3343 significand
3344 bin. decimal
3345 IEEE binary64 double 53 15.95
3346 8087 80-bit extended long double 64 19.27
3347 double-double 107 31.21
3348 IEEE binary128 quad 113 34.01
3349
3350The following variables (k_xxx_digits and fmt_g_xxx) are variables
3351initialized at runtime because at some point in the future, RIES might
3352support one of the higher precisions, selectable at runtime -- and also,
3353there might be a new option to select the number of digits that are
3354considered "nominal" and "usable", and how many get printed.
3355
3356*/
3357
3358/*
3359significant digits constants, pre-initialized for IEEE binary64.
3360
3361The number of "nominal" digits is the significand (decimal) value above,
3362rounded to an integer.
3363
3364The number of "usable" digits is based on the this and our choice of
3365k_sig_loss to limit loss of significance. k_sig_loss is 0.01 by default,
3366which is 10^-2 so we lose 2 digits of significance.
3367
3368NOTE: If RIES_VAL_LDBL (or some other precision) is defined, these will get
3369set to different values at runtime in init.formats()
3370 */
3371
3372int k_nominal_digits = 17;
3373int k_usable_digits = 15;
3374ries_dif k_ulp = 0.0625;
3375float k_mantissa_bits;
3376
3377ries_val rv_maxint; /* Largest integer that we can rely on measuring */
3378
3379/* Formatting strings, pre-initialized for IEEE binary64. 'nominal'
3380and 'usable' are as defined above. Note that some binary formats
3381(anything that is not compiler-native, like double-double) will not
3382use these format strings, but instead only use the k_xxx_digits values
3383above, because the library xxprintf() functions only work with
3384compiler-native formats.
3385
3386The 'fixed' strings are designed for fitting any value in a fixed
3387number of characters, so output lines up in neat columns. This has to
3388be 6 characters wider than the number of significant figures: 1 for
3389the sign, 1 for the decimal point, and 4 for an exponent like "e+27"
3390or "e-05". These strings from the output of "ries 2.5063 -DG" serve
3391as examples:
3392
3393 |123456789.123456789.1| <- 21 characters wide
3394 +---------------------+ left-justified printf format: "%-21.15g"
3395 |748.729680171193 | common case: 1+15 = 16 characters
3396 |0.470252846911253 | leading zero: 1+1+15 = 17 characters
3397 |-0.000131760338472132| sign and 4 leading zeros: 1+1+1+3+15 = 21 characters
3398 |-5.80064296934474e-05| sign, decmial, 'e', sign and exponent: 1+1+15+1+1+2
3399 +---------------------+
3400
3401*/
3402#define FMT_STR_SIZE 20
3403char fmt_g_nominal[FMT_STR_SIZE]; /* e.g. "%.17g" */
3404char fmt_g_nom_fixed[FMT_STR_SIZE]; /* e.g. "%-23.17g" */
3405
3406char fmt_g_usable[FMT_STR_SIZE]; /* e.g. "%.15g" */
3407char fmt_g_usa_fixed[FMT_STR_SIZE]; /* e.g. "%-21.15g" */
3408
3409char fmt_g_diff[FMT_STR_SIZE]; /* e.g. "%.7g" */
3410char fmt_g_dif_fixed[FMT_STR_SIZE]; /* e.g. "%-13.7g" */
3411
3412
3413/* Variables used by the search algorithm */
3414ries_val best_match;
3415
3416stats_count g_ne;
3417long insert_count;
3418stats_count prune_count, lhs_prune, rhs_prune;
3419long mem_used_KiB;
3420unsigned long mem_used_bytes;
3421int out_expr_format;
3422#define OF_POSTFIX 0
3423#define OF_CONDENSED 1
3424#define OF_NORMAL 2
3425#define OF_FORTH 3
3426
3427long lhs_insert, rhs_insert;
3428stats_count lhs_gen, rhs_gen;
3429stats_count gen_total;
3430
3431/* Counters used by thrash_check to estimate how long it should have taken
3432 us to use a given chunk of memory */
3433long g_exec_calls;
3434long g_cv_calls;
3435
3436/* debugging options: */
3437/* numbers from "ries -l2 2.5063141592653589 -DJ | wc -l" */
3438s16 debug_S; /* try.solve 100 */
3439s16 debug_s; /* report.match: "show work" 277 */
3440 /* (values of all subexpressions) */
3441s16 debug_N; /* eval: sym, x and dx at each step 461 */
3442s16 debug_n; /* newton: x and dx at each step 136 */
3443s16 debug_o; /* check.match entry 539235 */
3444s16 debug_p; /* infix.preproc 112 */
3445s16 debug_Q; /* cv.simplify 51 */
3446s16 debug_q; /* check.match past 1st-stage test 140 */
3447s16 debug_m; /* ms_push, ms_pop, ms_peek, ms_undo 10247603 */
3448s16 debug_r; /* exec 1806085 */
3449 /* ge.2: UPPERCASE lowercase
3450 for LHS for rhs */
3451 /* exec: */
3452s16 debug_A; /* prune partial exec error 42836 87770 */
3453s16 debug_B; /* prune partial 0 or dx near 0 3173 2714 */
3454s16 debug_C; /* prune partial noninteger 81056 697227 */
3455 /* (using command: "ries -l2 1047 -i -DC") */
3456s16 debug_D; /* prune partial overflow 1751 4350 */
3457 /* full expr: */
3458s16 debug_E; /* prune expr already in database 102356 272746 */
3459s16 debug_F; /* canon.val 349368 848882 */
3460 /* (use: ries -l2 2.50631415926 --canon-reduction nr25 -DF) */
3461s16 debug_G; /* insert 96112 97337 */
3462s16 debug_0; /* dump entire database 1712490 */
3463 /* partial expr: */
3464s16 debug_H; /* rules 409175 816240 */
3465s16 debug_I; /* symbols to try 3904331 7759741 */
3466s16 debug_J; /* prune complexity 2579116 5102516 */
3467s16 debug_K; /* prune rules 257302 558199 */
3468s16 debug_L; /* prune symcount 61994 114453 */
3469 /* (use: ries -l2 2.50631415926 '-O-+/^v*qsrlLeEpf' -Dl) */
3470 /* ge_1: */
3471s16 debug_t; /* entry 11017 */
3472s16 debug_u; /* rminw and rmaxw calculation 48895 */
3473s16 debug_v; /* expressions generated 5525 */
3474s16 debug_w; /* gf_1 32922 */
3475s16 debug_x; /* add.rule 91 */
3476s16 debug_y; /* main loop 736 */
3477s16 debug_z; /* init and miscellaneous 55 */
3478s16 debug_M; /* memory allocation 46 */
3479
3480#define DBG_LHS 2
3481#define DBG_RHS 1
3482
3483/* -------------- variables used for special commands --------------------- */
3484
3485s16 g_enable_output; /* Enable normal ries output */
3486s16 g_eval_expr;
3487
3488/* For the --find.expression command */
3489#define MAX_FIND_EXPR 16
3490s16 g_num_find_expr;
3491symbol * g_find_expr[MAX_FIND_EXPR];
3492
3493
3494/* -------------- prototypes ---------------------------------------------- */
3495
3496void ieee_paranoia(void);
3497void init_formats(void);
3498void show_version(void);
3499void brief_help(void);
3500
3501void ries_strncpy(char * to, char * fr, int n);
3502ries_val ries_intpow(ries_val x, int p);
3503void ries_to_digits(ries_val x, char *s, int *expn, int *sign, int precision);
3504void ries_snprinf_int(char * to, int len, int x);
3505int ries_strlen(char * s);
3506void ries_bltr0(char * s);
3507void ries_spfg(char *s1, int length, char sign_flag, int precision,
3508 ries_val x);
3509void spfg(int prec, ries_val x);
3510void spff(int prec, ries_val x);
3511void ries_spfg_test(char *s1, int length, char sign_flag, int precision,
3512 ries_val x);
3513void msal_test_spfg(void);
3514
3515char * file_read(const char * filename);
3516void delimit_args(const char *rawbuf, size_t * nargs, char * * * argv);
3517
3518const char * err_string(s16 err);
3519const char * tagname(int t);
3520
3521time_flt gettime(void);
3522void inittime(void);
3523int bitcount(unsigned long x);
3524void thrash_check(long alloced);
3525void init_mem(void);
3526void * my_alloc(size_t size);
3527void purgeall_mem(void);
3528
3529void ms_init(metastack *ms);
3530void ms_push(metastack *ms, ries_val x, ries_dif dx, ries_tgs tags);
3531ries_val ms_pop(metastack *ms, ries_dif *diff, ries_tgs * tags);
3532ries_val ms_peek(metastack *ms, ries_dif *diff, ries_tgs * tag, s16 *sptr);
3533void ms_undo(metastack *ms);
3534
3535s16 exec(metastack *ms, symbol op, s16 *undo_count, s16 do_dx);
3536
3537s16 infix_1(symbol * expr, char * term, symbol * t_op);
3538void cv_phantoms(symbol * s);
3539void infix_preproc(symbol * expr, symbol * out);
3540
3541symbol * symstrsym(symbol * exp1, symbol sym);
3542unsigned int symstrlen(symbol * s);
3543int symstrtrail(symbol * big, symbol * little);
3544int bothtrail(symbol * a, symbol * b, symbol *tr);
3545void symstrclip(symbol * s, unsigned int len);
3546int symstrcmp(symbol * a, symbol * b);
3547int symstrneq(symbol * a, symbol * b, unsigned int n);
3548symbol * symstrsymstr(symbol * haystack, symbol * needle);
3549int symstrncpy0(symbol *to, symbol *from, int len);
3550void symstrncat(symbol *to, symbol *from, long len);
3551void str_remap(char *s, char from, char to);
3552
3553s16 infix_expand(char * input, char * output);
3554s16 postfix(symbol * expr, char * term);
3555s16 postfix_formatter(symbol * expr, char * out, s16 maxlen);
3556s16 complexity(symbol * expr);
3557
3558int endstack(symbol * expr, int *ending_sp, symbol * * last_sp_1,
3559 symbol * * last_sym);
3560int expr_break(symbol * expr, symbol * op, symbol * seft,
3561 symbol * * arg1, int * a1_len, symbol * * arg2, int * a2_len);
3562void expr_print_infix(symbol * expr, int justify);
3563void eqn_print_infix(symbol * lhs, symbol * rhs);
3564
3565s16 eval(symbol * expr, ries_val * val, ries_dif * dx, ries_tgs * tags,
3566 s16 * sptr, s16 show_work);
3567void try_solve(symbol * l, symbol * r,
3568 symbol * l_out, int l_len, symbol * r_out, int r_len);
3569s16 newton(symbol * lhs, symbol * rhs, ries_val *root, ries_dif *diff_dx,
3570 ries_tgs *tags);
3571s16 cv_simplify(symbol * lhs, symbol * rhs, ries_val *root, ries_dif *diff_dx,
3572 ries_tgs *tags, int do_newton);
3573void defsym_used(symbol * expr);
3574void describe_symbols(void);
3575char * pf_intfloat_wid(stats_count x, int width);
3576void print_end(int exit_code);
3577void check_exit(int is_exact);
3578void report_match(symbol * lhs, symbol * rhs, symbol * exm,
3579 ries_val root, ries_dif delta, int did_newton);
3580int check_match(expr * lhs, expr * rhs);
3581
3582expr * bt_first(expr * tree);
3583int bt_depth(expr * it);
3584expr * bt_prev(expr *it);
3585expr * bt_next(expr *it);
3586void check_sides(expr * it);
3587void check_exact_match(expr * it, ries_dif new_dx, pe *ex);
3588s16 bt_insert(ries_val x, ries_dif dx, ries_tgs tg, pe *ex, s16 * res1);
3589s16 canonval(pe * bpe, metastack * ms, ries_val *p_x, ries_dif *p_dx,
3590 ries_tgs *p_tg, s16 * muc_ptr, s16 using_x);
3591void decanon(metastack * ms, s16 muc);
3592
3593stats_count ge_2(form *base, pe *bpe, s16 e_minw, s16 e_maxw,
3594 metastack *ms, s16 using_x);
3595
3596stats_count ge_1(form *base, s16 e_minw, s16 e_maxw, s16 using_x,
3597 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw);
3598stats_count gf_1(form *base, s16 minw, s16 maxw, s16 using_x,
3599 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw);
3600stats_count gen_forms(s16 minw, s16 maxw, s16 using_x,
3601 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw);
3602
3603void def_amkey(const char * syms, attr_bits mask);
3604void define_amkeys(void);
3605
3606void add_symbol(symbol sym, const char *name_forth, const char *name_infix,
3607 symbol type, s16 weight,
3608 const char * def_terse, const char * def_normal, const char * description);
3609/* The macro ADDSYM_NAMES is used to pass the four variants of a symbol's
3610 name, using the macro helps make the calls to add.symbol() a bit more
3611 readable. */
3612#define ADDSYM_NAMES(ascii1,FORTH,infix) (ascii1), (FORTH), (infix)
3613
3614void setup_abc_mmw(void);
3615
3616void show_symset(void);
3617void add_rule(const char * symset, char sym, attr_bits mask);
3618void init_numerics(void);
3619void init_symbol_names(void);
3620void allsyms_set(s16 n, int include_x);
3621void somesyms_set(symbol * s, s16 n);
3622void set_anagram(char * anagram);
3623void init1(void);
3624void init2(void);
3625int unique_eqn(symbol * lhs, symbol * rhs, int addit);
3626int parse_target(char *str);
3627void set_debug_opts(char * str);
3628void set_restrict_rat(void);
3629void set_restrict_alg(int restrict_trig);
3630char * pa_defaults_path(void);
3631char * pa_next_peek(void);
3632int pa_next_isparam(void);
3633char * pa_get_arg(void);
3634char * pa_stk_pop(void);
3635void parse_args(size_t nargs, char *argv[]);
3636void validate_types(void);
3637ries_tgs guess_valtype(ries_val v);
3638int main(int nargs, char *argv[]);
3639
3640/* -------------- functions ----------------------------------------------- */
3641
3642char * pa_def_path;
3643
3644void show_version(void)
3645{
3646 printf(
3647 "ries version of %s, Copyright (C) 2000-2016 Robert P. Munafo\n",
3648 RIES_VERSION);
3649
3650 printf(
3651 " architecture: %s\n",
3652#ifdef __POWERPC__
3653 "PowerPC"
3654#else
3655# ifdef __i386__
3656 "Intel-32"
3657# else
3658# ifdef __x86_64__
3659 "Intel-64"
3660# else
3661 "Unknown"
3662# endif
3663# endif
3664#endif
3665 );
3666
3667 printf(
3668 " precision: %s (%d nominal, %d usable)\n",
3669#ifdef RIES_VAL_LDBL
3670 "long double",
3671#else
3672 "double",
3673#endif
3674 k_nominal_digits, k_usable_digits
3675 );
3676
3677 printf(
3678 " mathlib: %s\n",
3679#ifdef RIES_USE_SA_M64
3680 "stand-alone"
3681#else
3682 "standard"
3683#endif
3684 );
3685
3686 printf(" MAX_ELEN == %d\n", MAX_ELEN);
3687
3688 if (pa_def_path) {
3689 printf(" profile: %s\n", pa_def_path);
3690 }
3691
3692#ifdef RIES_USE_SA_M64
3693 printf("\n");
3694 msal_version_info();
3695#endif
3696
3697 printf("\n");
3698 printf("%s",
3699"RIES is provided under the GPL license v3. Source code at mrob.com/ries\n"
3700"This is free software; see the source for copying conditions. There is NO\n"
3701"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3702 );
3703}
3704
3705void brief_help(void)
3706{
3707 printf("%s",
3708"Usage:\n"
3709" ries [options] target-value\n"
3710"\n"
3711"Target value is required and may be any number. Options include:\n"
3712" -l3 Search further (``level-3 search'')\n"
3713" -x Show matched values as ``x = value'' rather than ``x = T + epsilon''\n"
3714" -s (Sort of) solve by transforming to ``x = ...'' form\n"
3715" -N+-/ Do not use symbols +, - or /\n"
3716" -S Show list of all available symbols\n"
3717); printf("%s",
3718" -l Restrict to Liouvillian solutions\n"
3719" -a Restrict to algebraic solutions\n"
3720" -c Restrict to ``constructible'' (straightedge and compass) solutions\n"
3721" -r Restrict to rational solutions (-re for exact match)\n"
3722" -i Restrict to integer solutions (-ie for exact match)\n"
3723"\n"
3724"There are many more options; get the full manual at mrob.com/ries\n"
3725);
3726} /* End of brief.help */
3727
3728/* -------------- formatting and conversion ------------------------------- */
3729
3730/* Copy a string as if by strncpy */
3731void ries_strncpy(char * to, char * fr, int n)
3732{
3733 int i;
3734 for(i=0; (i<n) && fr[i]; i++) {
3735 to[i] = fr[i];
3736 }
3737 /* copy the final 0 if we have room */
3738 if (i<n) {
3739 to[i] = fr[i];
3740 }
3741}
3742
3743/* Raise any value to an integer power. */
3744ries_val ries_intpow(ries_val x, int p)
3745{
3746 int i;
3747 ries_val rv;
3748 ries_val pow2;
3749 int recip = 0;
3750
3751 pow2 = x;
3752
3753 if (p < 0) {
3754 p = -p;
3755 recip = 1;
3756 if (p < 0) {
3757 /* p was MININT */
3758 p = p / 2;
3759 p = -p;
3760 pow2 = x * x;
3761 }
3762 }
3763
3764 rv = 1.0;
3765 pow2 = x;
3766 i = p;
3767 while(i > 0) {
3768 if (i & 1) {
3769 rv = rv * pow2;
3770 }
3771 i >>= 1;
3772 if (i) {
3773 /* We could do better here by a special-case for x near 1.0 */
3774 pow2 = pow2 * pow2;
3775 }
3776 }
3777
3778 if (recip) {
3779 return(1.0 / rv);
3780 }
3781 return(rv);
3782} /* End of ries_intpow */
3783
3784/* This routine returns the first N significant digits of an ries_val
3785 value. It goes to fairly thorough measures to ensure that rounding
3786 is done properly. You supply a string with a little bit more than
3787 the needed amount of space, and (if desired) an integer in which to
3788 store the exponent. */
3789void ries_to_digits(ries_val x, char *s, int *expn, int *sign, int precision)
3790{
3791 int dig1 = precision + 1; /* number of digits to compute */
3792
3793 ries_val r; /* "remainder", the portion not yet turned into digits. */
3794 ries_val pw;
3795 int e; /* exponent */
3796 int i, d;
3797 int sgn;
3798
3799 if (x <= k_d_ninf) {
3800 ries_strncpy(s, (char *) "-inf", precision);
3801 return;
3802 } else if (x >= k_d_inf) {
3803 ries_strncpy(s, (char *) "+inf", precision);
3804 return;
3805 } else if (!((x > k_d_ninf) && (x < k_d_inf))) {
3806 ries_strncpy(s, (char *) "NaN", precision);
3807 return;
3808 }
3809
3810 sgn = 0;
3811 if (x < 0.0) {
3812 x = - x;
3813 sgn = 1;
3814 }
3815 if (sign) {
3816 *sign = sgn;
3817 }
3818
3819 r = (x<0) ? (-x) : x;
3820
3821 if (x == 0.0) {
3822 /* x == 0.0 */
3823 if (expn) {
3824 *expn = 0;
3825 }
3826 for (i = 0; i < precision; i++)
3827 s[i] = '0';
3828 return;
3829 }
3830
3831 /* First determine the (approximate) exponent. */
3832 e = (int) (FLOOR(LOG10(FABS(x))));
3833
3834 if (e < -300) {
3835 r = r * ries_intpow(10.0, 300);
3836 pw = ries_intpow(10.0, (e + 300));
3837 r = r / pw;
3838 } else if (e > 0) {
3839 pw = ries_intpow(10.0, e);
3840 r = r / pw;
3841 } else if (e < 0) {
3842 pw = ries_intpow(10.0, -e);
3843 r = r * pw;
3844 }
3845
3846 /* Fix exponent if we are off by one */
3847 if (r >= 10.0) {
3848 r = r / 10.0;
3849 e++;
3850 } else if (r < 1.0) {
3851 r = r * 10.0;
3852 e--;
3853 }
3854
3855 if (r >= 10.0 || r < 1.0) {
3856 fprintf(stderr, "ries_to_digits: exponent adjust failed (x=%g, r=%g).\n",
3857 ((double) x), ((double) r));
3858 return;
3859 }
3860
3861 /* Extract the digits */
3862 for (i = 0; i < dig1; i++) {
3863 d = ((int) r);
3864 r = r - ((ries_val) d);
3865 r = r * 10.0;
3866
3867 s[i] = ((char)(((int)'0') + d));
3868 }
3869
3870 /* Fix negative digits. */
3871 for (i = dig1-1; i > 0; i--) {
3872 if (s[i] < '0') {
3873 s[i-1]--;
3874 s[i] = ((char)(((int)(s[i])) + 10));
3875 }
3876 }
3877
3878 if (s[0] <= '0') {
3879 fprintf(stderr, "ries_to_digits: non-positive leading digit.\n");
3880 return;
3881 }
3882
3883 /* Round, handle carry */
3884 if (s[dig1-1] >= '5') {
3885 s[dig1-2]++;
3886
3887 i = dig1-2;
3888 while (i > 0 && s[i] > '9') {
3889 s[i] = ((char)(((int)(s[i])) - 10));
3890 i--;
3891 s[i] = ((char)( ((int)(s[i])) + 1));
3892 }
3893 }
3894
3895 /* If first digit is 10, shift everything. */
3896 if (s[0] > '9') {
3897 e++;
3898 for (i = precision; i >= 2; i--) s[i] = s[i-1];
3899 s[0] = '1';
3900 s[1] = '0';
3901 }
3902
3903 s[precision] = 0;
3904 if (expn) *expn = e;
3905} /* End of ries_to_digits */
3906
3907/* Format an int into a string as if by snprintf */
3908void ries_snprinf_int(char * to, int len, int x)
3909{
3910 char * s;
3911 int x2, i;
3912 char c;
3913
3914 s = to;
3915 if(len <= 0) {
3916 return;
3917 }
3918 /* Reserve space for trailing null */
3919 len--;
3920 if (len <= 0) {
3921 /* If that's all we have, leave now */
3922 *s++ = 0;
3923 return;
3924 }
3925 if (x<0) {
3926 *s++ = '-'; len--;
3927 x = -x;
3928 }
3929 if (len <= 0) { *s++ = 0; return; }
3930
3931 /* Handle 0 */
3932 if (x == 0) {
3933 *s++ = '0';
3934 *s = 0;
3935 return;
3936 }
3937
3938 /* Find out if int will fit */
3939 x2 = x;
3940 while(x2>0) {
3941 len--;
3942 x2 = x2 / 10;
3943 }
3944 if (len <= 0) { *s++ = 0; return; }
3945
3946 /* Write digits in reverse order */
3947 len = 0; /* len now counts number of digits output */
3948 x2 = x;
3949 while(x2 > 0) {
3950 s[len] = ((char)(((int)'0') + (x2 % 10)));
3951 len++;
3952 x2 = x2 / 10;
3953 }
3954 /* Trailing null */
3955 s[len] = 0;
3956
3957 /* Reverse the string in place */
3958 for(i=0; i<len/2; i++) {
3959 c = s[i]; s[i] = s[len-1-i]; s[len-1-i] = c;
3960 }
3961
3962 /* We're done */
3963} /* End of ries_snprinf_int */
3964
3965/* Measure the length of a string as if by strlen */
3966int ries_strlen(char * s)
3967{
3968 int i;
3969 for(i=0; s[i]; i++) {
3970 }
3971 return i;
3972}
3973
3974/* Blank out trailing '0' digits in a string */
3975void ries_bltr0(char * s)
3976{
3977 char *t;
3978
3979 /* Return right away on null inputs */
3980 if ((s == 0) || (!(*s))) {
3981 return;
3982 }
3983
3984 /* Find the end of s */
3985 for(t=s; *t; t++) { }
3986
3987 /* Back up one character */
3988 t--;
3989
3990 /* Keep backing up and nulling out chars as long as they're 0's */
3991 while((t >= s) && (*t == '0')) {
3992 *t = 0;
3993 t--;
3994 }
3995}
3996
3997/* ries_spfg prints an ries_val into a string, using format similar to
3998 the standard C library printf("%10.3g", val). There is a length field,
3999 controlling the maximum length of output and a precision field
4000 specifying how many digits you want. For best results the length should
4001 be at least precision+8, to allow for the worst case of the sign,
4002 decimal point, "e", exponent sign, and 3-digit exponent plus the trailing
4003 null. For example, the string "-1.23e-123" has "precision" 3, but is
4004 7 characters longer than the precision.
4005
4006 The parameters are:
4007
4008 char * s1 - output string. Must have at least as many bytes as the
4009 parameter 'length'
4010 length - length of the buffer s1. No more than length-1 printable
4011 chars will be emitted, followed by a null.
4012 sign_flag - pass in '+' if you want explicit + signs; pass anything
4013 else to have no '+' signs.
4014 precision - number of significant digits to generate.
4015 ries_val x - the number to format.
4016
4017 For the opposite conversion, use ries_sscan.
4018 */
4019void ries_spfg(char *s1, int length, char sign_flag, int precision,
4020 ries_val x)
4021{
4022 char *s;
4023 int sign;
4024 int exponent;
4025 int i;
4026 char s2[40];
4027 char sexp[8]; /* Signed exponent as a string */
4028
4029 s = s1;
4030
4031 /* Handle unreasonably short output buffers */
4032 if (length <= 0) {
4033 return;
4034 } else if (length < 8) {
4035 for(i=0; i<(length-1); i++) {
4036 s[i] = '!';
4037 }
4038 s[i] = 0;
4039 return;
4040 }
4041
4042 if (x <= k_d_ninf) {
4043 ries_strncpy(s, (char *) "-inf", precision);
4044 return;
4045 } else if (x >= k_d_inf) {
4046 ries_strncpy(s, (char *) "+inf", precision);
4047 return;
4048 } else if (!((x > k_d_ninf) && (x < k_d_inf))) {
4049 ries_strncpy(s, (char *) "NaN", precision);
4050 return;
4051 }
4052
4053 if (precision > 35) {
4054 precision = 35;
4055 } else if (precision < 1) {
4056 precision = 1;
4057 }
4058
4059 ries_to_digits(x, s2, &exponent, &sign, precision);
4060
4061 if (sign) {
4062 *s++ = '-'; length--;
4063 } else if (sign_flag == '+') {
4064 *s++ = '+'; length--;
4065 }
4066
4067 if ((exponent > 0) && (exponent < precision)) {
4068 /* It can be formatted as a normal number without an exponent field */
4069 /* length needs to be at least enough for lead digits and trailing null */
4070 if (length < exponent+2) {
4071 ries_strncpy(s, (char *) "fmt-err", length);
4072 return;
4073 }
4074 i = 0;
4075 /* Emit lead digit */
4076 *s++ = s2[i++]; length--;
4077 /* Emit the rest of the digits before the decimal point */
4078 while (exponent) {
4079 *s++ = s2[i++]; length--;
4080 exponent--;
4081 }
4082
4083 /* Check the rest of the digits for trailing 0's */
4084 ries_bltr0(s2);
4085 if (*s2 == 0) {
4086 *s++ = 0;
4087 return;
4088 }
4089
4090 if (length > 1) {
4091 *s++ = '.'; length--;
4092 }
4093 for(; s2[i] && (i<precision) && (length > 1); i++) {
4094 *s++ = s2[i]; length--;
4095 }
4096 *s++ = 0;
4097 return;
4098
4099 } else if (exponent == 0) {
4100 /* Values from 1.00000 to 9.99999 */
4101 /* length needs to be at least enough for lead digit, decimal point
4102 and trailing null */
4103 if (length < 3) {
4104 ries_strncpy(s, (char *) "!!!", length);
4105 return;
4106 }
4107 *s++ = s2[0]; length--; /* Lead digit */
4108
4109 /* Check the rest of the digits for trailing 0's */
4110 ries_bltr0(s2+1);
4111 if (s2[1] == 0) {
4112 *s++ = 0;
4113 return;
4114 }
4115
4116 *s++ = '.'; length--;
4117 for(i=1; s2[i] && (i<precision) && (length > 1); i++) {
4118 *s++ = s2[i]; length--;
4119 }
4120 *s++ = 0;
4121 return;
4122
4123 } else if ((exponent < 0) && (exponent > -5)) {
4124 /* Values like 0.12345, 0.012345, etc. */
4125 /* Length needs to be enough for leading 0's, decimal point, one
4126 significant digit, and trailing null */
4127 if (length+exponent < 3) {
4128 ries_strncpy(s, (char *) "fmt-err", length);
4129 return;
4130 }
4131
4132 /* Add a suitable number of zeros */
4133 *s++ = '0'; length--;
4134 *s++ = '.'; length--;
4135 exponent++;
4136 while ((exponent < 0) && (length > 1)) {
4137 *s++ = '0'; length--;
4138 exponent++;
4139 }
4140
4141 /* Remove extra trailing 0's */
4142 ries_bltr0(s2);
4143 if (*s2 == 0) {
4144 *s++ = 0;
4145 return;
4146 }
4147
4148 for(i=0; s2[i] && (i<precision) && (length > 1); i++) {
4149 *s++ = s2[i]; length--;
4150 }
4151 *s++ = 0;
4152 return;
4153
4154 }
4155
4156 /* General case: use scientific notation */
4157
4158 /* Get the exponent as a string */
4159 if (exponent >= 0) {
4160 sexp[0] = '+';
4161 ries_snprinf_int(sexp+1, sizeof(sexp)-1, exponent);
4162 } else {
4163 /* ries_snprinf_int will print the '-' sign */
4164 ries_snprinf_int(sexp, sizeof(sexp), exponent);
4165 }
4166
4167 /* Here we are a little forgiving about the length: We'll deduct the
4168 space we need for the signed exponent and 'e', then emit as many
4169 digits as we can. Note that s2[] already has the requested number
4170 of digits. So we just need to make sure the length can accommodate
4171 the lead digit, decimal point and exponent. */
4172 if (length - (1 + 1 + 1 + ries_strlen(sexp)) < 1) {
4173 ries_strncpy(s, (char *) "fmt-err", length);
4174 return;
4175 }
4176
4177 /* Reserve space for 'e' and exponent and null */
4178 length = length - (1 + ries_strlen(sexp) + 1);
4179
4180 *s++ = s2[0]; length--; /* Lead digit */
4181
4182 ries_bltr0(s2+1);
4183 if (s2[1]) {
4184 /* We have some nonzero digits to print */
4185 *s++ = '.'; length--;
4186 for(i=1; (i<precision) && s2[i] && (length > 0); i++) {
4187 *s++ = s2[i]; length--;
4188 }
4189 }
4190 *s++ = 'e'; length--;
4191 /* We now have just enough room for the exponent */
4192 for(i=0; sexp[i]; i++) {
4193 *s++ = sexp[i];
4194 }
4195 *s++ = 0;
4196} /* End of ries_spfg */
4197
4198/* Print a ries_val as if by printf("%.23g", x) where the precision is
4199given by the parameter 'prec'. */
4200void spfg(int prec, ries_val x)
4201{
4202 char tmp[100];
4203 ries_spfg(tmp, 100, 0, prec, x);
4204 printf("%s", tmp);
4205}
4206
4207/* Print a ries_val as if by printf("%29.23g", x) where the precision is
4208given by the parameter 'prec'. */
4209void spff(int prec, ries_val x)
4210{
4211 char tmp[100]; char fmt[FMT_STR_SIZE];
4212 ries_spfg(tmp, 100, 0, prec, x);
4213 snprintf(fmt, FMT_STR_SIZE, "%%-%ds", prec+6);
4214 printf(fmt, tmp);
4215}
4216
4217#ifdef RIES_USE_SA_M64
4218
4219float g_min_spfg_mbits = 256.0;
4220ries_val g_worst_spfg_inpt;
4221
4222/* Wrapper for ries_spfg that converts the result string back to a ries_val
4223and watches for the worst result */
4224void ries_spfg_test(char *s1, int length, char sign_flag, int precision,
4225 ries_val x)
4226{
4227 ries_val xc;
4228 int nv;
4229
4230 ries_spfg(s1, length, sign_flag, precision, x);
4231 nv = sscanf(s1, RV_SS_FMT, &xc);
4232 if ((nv) && (x != 0)) {
4233 ries_val rat, diff;
4234 float db;
4235 rat = xc / x;
4236 diff = rat - 1.0;
4237 if (diff < 0) {
4238 diff = 0 - diff;
4239 }
4240 if (diff > 0) {
4241 db = 0.0;
4242 while (diff < 1.0) {
4243 db = db + 1.0f;
4244 diff *= 2.0;
4245 }
4246
4247 if (db < g_min_spfg_mbits) {
4248 g_min_spfg_mbits = db;
4249 g_worst_spfg_inpt = x;
4250 if (debug_z) {
4251 printf("New poorest conversion (%g bits)"
4252 " from input %23.17g -> '%s'\n", db, ((double)x), s1);
4253 }
4254 }
4255 }
4256 }
4257} /* end of ries_spfg_test */
4258
4259/* Generate a huge number of values and test conversion via ries_spfg */
4260void msal_test_spfg(void)
4261{
4262 int ei, n;
4263 ries_val eps; /* epsilon */
4264 ries_val k8, k10;
4265
4266 printf("msal_test_spfg: starting...\n"); n = 0;
4267 eps = 0.5;
4268 k8 = 8.0; k10 = 10.0;
4269 /* Test each epsilon */
4270 for(ei=0; ei<100; ei++) {
4271 ries_val b8, b10; /* "big" test values */
4272 ries_val s8, s10; /* "big" test values */
4273 int di;
4274
4275 for (di=0; di<2; di++) {
4276 int si;
4277 if (di == 0) {
4278 b8 = b10 = s8 = s10 = 1.0 - eps;
4279 } else {
4280 b8 = b10 = s8 = s10 = 1.0 + eps;
4281 }
4282 /* Run through range of large and small values */
4283 for(si=0; si<100; si++) {
4284 char tmp[100];
4285 int si;
4286 /* Make values bigger/smaller */
4287 b8 = b8 * k8; b10 = b10 * k10;
4288 s8 = s8 / k8; s10 = s10 / k10;
4289 for(si=0; si<2; si++) {
4290 ries_spfg_test(tmp, 100, 0, k_nominal_digits, b8); n++;
4291 ries_spfg_test(tmp, 100, 0, k_nominal_digits, b10); n++;
4292 ries_spfg_test(tmp, 100, 0, k_nominal_digits, s8); n++;
4293 ries_spfg_test(tmp, 100, 0, k_nominal_digits, s10); n++;
4294 /* Negate everything */
4295 b8 = -b8; b10 = -b10; s8 = -s8; s10 = -s10;
4296 }
4297 }
4298 /* Go to the next epsilon */
4299 eps = eps * 0.375;
4300 }
4301 }
4302 printf("msal_test_spfg: %d tests completed.\n", n);
4303}
4304
4305#endif /* RIES_USE_SA_M64 */
4306
4307/* -------------- profiles and argument parsing --------------------------- */
4308
4309#define FILE_READ_SIZE 1024
4310#define FILE_READ_MAX 10*1024*1024
4311char * file_read(const char * filename)
4312{
4313 FILE * in;
4314 size_t buf_sz;
4315 char * base_ptr;
4316 size_t t_len;
4317
4318 /* We read in binary mode to avoid having the OS change anything. In
4319 particular, by definition the RIES profile format is not a "text" file
4320 format, it is "a sequence of text-like tokens separated by
4321 non-text bytes". Right now we treat all control characters as
4322 token-delimiters (and additionally as an end-of-comment delimiter in
4323 most cases if after a '#') but I may want to change that in the future.
4324 */
4325 in = fopen(filename, "rb");
4326 if (in == NULL) {
4327 char * name_ext;
4328 /* Try appending ".ries"
4329 (Allocation and UNIX compatibility by Markus Milleder, 20120428) */
4330 /* The typecast to "(char *)" avoids the warning "request for implicit
4331 conversion from 'void *' to 'char *' not permitted in C++" given by
4332 the option -Wc++-compat */
4333 t_len = strlen(filename) + 6; /* + ".ries\0" */
4334 name_ext = (char *) malloc(t_len);
4335 if (name_ext) {
4336 snprintf(name_ext, t_len, "%s.ries", filename);
4337 in = fopen(name_ext, "rb");
4338 free(name_ext);
4339 }
4340 }
4341
4342 if (in == NULL) {
4343 fprintf(stderr, "%s: Could not open '%s' or '%s.ries' for reading.\n"
4344 "\n\n", g_argv0, filename, filename);
4345 brief_help();
4346 print_end(-1);
4347 }
4348
4349 buf_sz = FILE_READ_SIZE;
4350 base_ptr = (char *) malloc(buf_sz);
4351 t_len = 0;
4352
4353 while (!feof(in) && !ferror(in)) {
4354 if (t_len + FILE_READ_SIZE > buf_sz) {
4355 /* The next read might go beyond the allocated memory, so we need to
4356 reallocate */
4357 if (buf_sz > FILE_READ_MAX) break;
4358 buf_sz = buf_sz * 2;
4359 base_ptr = (char *) realloc(base_ptr, buf_sz);
4360 }
4361 {
4362 /* Now read a little bit more */
4363 char * p = base_ptr + t_len;
4364 t_len += fread(p, 1, FILE_READ_SIZE, in);
4365 }
4366 }
4367
4368 fclose(in);
4369
4370 /* Reallocate again to free up the memory we didn't use. */
4371 base_ptr = (char *) realloc(base_ptr, t_len + 1);
4372
4373 /* It needs a trailing null byte */
4374 base_ptr[t_len] = 0;
4375
4376 return base_ptr;
4377} /* End of file_read */
4378
4379/* "A RIES argument-file is a sequence of one or more non-blank words
4380 separated by blanks." */
4381void delimit_args(const char *rawbuf, size_t * nargs, char * * * argv)
4382{
4383 size_t n;
4384 char ** av;
4385
4386 n = 0;
4387 av = 0;
4388
4389 if (nargs) { *nargs = n; }
4390 if (argv) { *argv = av; }
4391
4392 if (rawbuf) {
4393 unsigned char * p;
4394
4395 n = 0;
4396
4397 /* Scan for and canonicize whitespace. */
4398 p = (unsigned char *) rawbuf;
4399 while(*p) {
4400 /* Skip any leading space */
4401 while(*p && ((*p <= ' ') || (*p == '\177'))) { *p = ' '; p++; }
4402 if (*p == '#') {
4403 /* Comment delimiter. Change everything to space until we get to
4404 a non-tab control character, which we assume is an end of line */
4405 while(*p && ((*p == '\t') || (*p >= ' '))) { *p = ' '; p++; }
4406 } else if (*p && (*p > ' ')) {
4407 /* A word that doesn't start with '#' is an arg; skip it */
4408 while(*p && (*p > ' ')) { p++; }
4409 }
4410
4411 /* We are now at a null or a delimiter; loop can now continue. */
4412 }
4413
4414 /* Count up the strings */
4415 p = (unsigned char *) rawbuf;
4416 while(*p) {
4417 /* Skip any leading space */
4418 while(*p == ' ') { p++; }
4419
4420 /* If there is an arg, count it */
4421 if (*p) {
4422 n++;
4423 /* Skip the nonspace */
4424 while(*p && (*p != ' ')) { p++; }
4425 }
4426
4427 /* We are now at a null or a blank space; loop can now continue. */
4428 }
4429
4430 /* Now n is the number of args, and we can allocate the argv */
4431 av = (char **) malloc(n * sizeof(char *));
4432 if (av == 0) {
4433 fprintf(stderr, "%s: Cannot alloate argv block.\n", g_argv0);
4434 print_end(-1);
4435 }
4436 if (nargs) { *nargs = n; }
4437 if (argv) { *argv = av; }
4438
4439 /* Set pointers, marking with nulls as we go */
4440 p = (unsigned char *) rawbuf;
4441
4442 while(*p) {
4443 /* Skip any leading space and turn it into nulls */
4444 while(*p == ' ') { *p = 0; p++; }
4445
4446 /* If there is an arg, count it */
4447 if (*p) {
4448 /* Save a pointer to this string, with (paranoid) check to avoid
4449 overwriting the argv */
4450 if (n > 0) {
4451 *av = (char *) p;
4452 av++;
4453 n--;
4454 }
4455 /* Skip the nonspace */
4456 while(*p && (*p != ' ')) { p++; }
4457 }
4458
4459 /* We are now at a null or a blank space; loop can now continue. */
4460 }
4461 }
4462} /* End of delimit_args */
4463
4464/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4465 Error codes and strings
4466_____________________________________________________________________________*/
4467
4468#define ERR_EXEC_DIV_ZERO -1
4469#define ERR_EXEC_ROOT_NEG -2
4470#define ERR_EXEC_LOG_NEG -3
4471#define ERR_EXEC_OVERFLOW -4
4472#define ERR_EXEC_TRIG_RANGE -5
4473#define ERR_EXEC_TRIG_LOW_DX -6
4474#define ERR_EXEC_SIG_LOSS -7
4475#define ERR_EXEC_POW_NEG_BASE -8
4476#define ERR_EXEC_LOG_BAD_BASE -9
4477#define ERR_EXEC_ILLEGAL_SYMBOL -10
4478#define ERR_NEWTON_ZERO_DX -11
4479#define ERR_NEWTON_NO_CONVERGE -12
4480#define ERR_EVAL_TOO_LONG -13
4481#define ERR_EVAL_METASTACK_OVERFLOW -14
4482#define ERR_EVAL_UNKNOWN_SEFT -15
4483#define ERR_EVAL_STACK_OVERFLOW -16
4484#define ERR_EVAL_STACK_UNDERFLOW -17
4485#define ERR_ES_NULL_EXPRESSION -18
4486#define ERR_EC_INCOMPLETE_EXPR -19
4487#define ERR_EXEC_ILLEGAL_EXPONENT -20
4488#define ERR_EXEC_TRIG_ARGTYPE -21
4489#define ERR_EXEC_ILLEGAL_DERIV -22
4490#define ERR_EXEC_ZERO_DERIV -23
4491/* Add any new ones here */
4492#define EXIT_NO_ERROR -9998
4493#define ERR_UNKNOWN -9999
4494
4495typedef struct err_str {
4496 s16 val;
4497 const char * str;
4498} err_str;
4499
4500err_str error_strings[] = {
4501 {0, "No Error"},
4502 {ERR_EXEC_DIV_ZERO, "Divide by zero"},
4503 {ERR_EXEC_ROOT_NEG, "Root of a negative value"},
4504 {ERR_EXEC_LOG_NEG, "Logarithm of a negative value"},
4505 {ERR_EXEC_OVERFLOW, "Overflow"},
4506 {ERR_EXEC_TRIG_RANGE, "Trigonometric argument out of range"},
4507 {ERR_EXEC_TRIG_LOW_DX, "Trigonometric argument generates near-constant"},
4508 {ERR_EXEC_SIG_LOSS, "Loss of significance"},
4509 {ERR_EXEC_POW_NEG_BASE, "Power of a negative base"},
4510 {ERR_EXEC_LOG_BAD_BASE, "Logarithm to base 1 or negative base"},
4511 {ERR_EXEC_ILLEGAL_SYMBOL, "Illegal symbol"},
4512 {ERR_NEWTON_ZERO_DX, "Zero derivative in Newton iteration"},
4513 {ERR_NEWTON_NO_CONVERGE, "Newton iteration did not converge"},
4514 {ERR_EVAL_TOO_LONG, "Expression is too long"},
4515 {ERR_EVAL_METASTACK_OVERFLOW, "Metastack overflow"},
4516 {ERR_EVAL_UNKNOWN_SEFT, "Symbol of unknown seft"},
4517 {ERR_EVAL_STACK_OVERFLOW, "Stack overflow"},
4518 {ERR_EVAL_STACK_UNDERFLOW, "Stack underflow"},
4519 {ERR_ES_NULL_EXPRESSION, "Null expression"},
4520 {ERR_EC_INCOMPLETE_EXPR, "Incomplete expression"},
4521 {ERR_EXEC_ILLEGAL_EXPONENT, "Disallowed exponent"},
4522 {ERR_EXEC_TRIG_ARGTYPE, "Disallowed trigonometric argument"},
4523 {ERR_EXEC_ILLEGAL_DERIV, "Overflow or NaN in derivative"},
4524 {ERR_EXEC_ZERO_DERIV, "Underflow in derivative"},
4525 /* Add any new ones here */
4526 {EXIT_NO_ERROR, "No error"},
4527 {ERR_UNKNOWN, "Unknown error"},
4528};
4529
4530const size_t g_num_errors = sizeof(error_strings) / sizeof(err_str);
4531
4532const char * err_string(s16 err)
4533{
4534 unsigned int j;
4535
4536 for(j=0; j<g_num_errors; j++) {
4537 if (error_strings[j].val == err) {
4538 return (error_strings[j].str);
4539 }
4540 }
4541 return(error_strings[g_num_errors-1].str);
4542}
4543
4544const char * tagname(int t)
4545{
4546 switch(t) {
4547 case TYPE_NONE: default: return "none";
4548 case TYPE_TRAN: return "tran";
4549 case TYPE_ELEM: return "elem";
4550 case TYPE_ALG: return "alg";
4551 case TYPE_CONS: return "cons";
4552 case TYPE_RAT: return "rat";
4553 case TYPE_INT: return "int";
4554 }
4555}
4556
4557/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4558 Time measurement, memory allocation, and "thrashing" detection
4559_____________________________________________________________________________*/
4560
4561time_flt tod_start; /* gettime() value at program start */
4562
4563/* gettime is the only really OS-specific routine in this whole program.
4564 It returns how long the program has been running, measured in tenths
4565 of a second. For example, it returns 14 if the program has run for
4566 1.4 seconds. This is actual elapsed "clock-on-the-wall" time, not
4567 necessarily a measure of how much time the CPU has spent working on
4568 RIES. For example, if you close your laptop while RIES is running it
4569 will include the time the system was "asleep" in its final printout
4570 of time used. */
4571time_flt gettime(void)
4572{
4573 struct timeval tod_record;
4574 time_flt t_now;
4575
4576 /* There is a block of code inside an #ifdef above (search for
4577 "---gettimeofday---") that sets up the appropriate include files
4578 and/or defines a gettimeofday() function based on compile-time flags
4579 like _WIN32. See the block-comment there for more details. */
4580
4581 gettimeofday(&tod_record, 0);
4582
4583 t_now = ((time_flt) (tod_record.tv_sec))
4584 + ((time_flt) (tod_record.tv_usec)) / 1.0e6;
4585
4586 return(t_now - tod_start);
4587}
4588
4589time_flt g_min_memory;
4590time_flt g_max_memory;
4591time_flt g_avg_alloc_rate, g_good_alloc_rate;
4592time_flt memstat_when;
4593long memstat_where, rate_where;
4594time_flt my_alloc_when, g_ttl_elapsed;
4595long tc_alloced;
4596long g_rate_increase_run, g_max_rir;
4597time_flt g_decay_slug;
4598unsigned long g_last_thrash;
4599
4600void inittime(void)
4601{
4602 time_flt now;
4603
4604 /* Init the global so gettime() has a valid value to subtract from
4605 its new measurement */
4606 tod_start = 0;
4607
4608 /* With tod_start set to 0 gettime will return the absolute current time */
4609 now = gettime();
4610
4611 /* Set the global to this value. */
4612 tod_start = now;
4613
4614 /* From now on, calls to gettime() will measure time from the moment we
4615 made the preceding gettime() call. */
4616
4617 g_avg_alloc_rate = g_good_alloc_rate = 0.0;
4618 my_alloc_when = memstat_when = gettime();
4619 tc_alloced = 0; memstat_where = rate_where = 0;
4620 g_cv_calls = 0; g_exec_calls = 0;
4621 g_ttl_elapsed = 0; g_rate_increase_run = g_max_rir = 0;
4622 g_last_thrash = 0;
4623}
4624
4625int bitcount(unsigned long x)
4626{
4627 x = ((x & 0xAAAAAAAAL) >> 1) + (x & 0x55555555L);
4628 x = ((x & 0xCCCCCCCCL) >> 2) + (x & 0x33333333L);
4629 x = ((x & 0xF0F0F0F0L) >> 4) + (x & 0x0F0F0F0FL);
4630 x = ((x & 0xFF00FF00L) >> 8) + (x & 0x00FF00FFL);
4631 x = (x >> 16) + (x & 0x0000FFFFL);
4632 return((int) x);
4633}
4634
4635time_flt g_mem_bad_ratio = 2.0;
4636
4637/* Try to detect if the system is "thrashing" (swapping memory pages in
4638and out from the hard drive) by measuring the elapsed time and comparing to
4639an estimate of how much time our computation should have taken. */
4640void thrash_check(long alloced)
4641{
4642 time_flt now, alloc_elapsed, predicted_rate;
4643 time_flt this_alloc_rate;
4644 time_flt decay_numer, decay_denom;
4645 time_flt sluggish_ratio;
4646
4647 tc_alloced += alloced;
4648 if (tc_alloced < (1024L*1024L)) {
4649 /* It's not time to benchmark memory yet... */
4650 return;
4651 }
4652
4653 /* Look at how much time has passed since the last time we were here */
4654 now = gettime();
4655 alloc_elapsed = now - my_alloc_when;
4656 /* Reset the timer for use next time */
4657 my_alloc_when = now;
4658
4659 /* Convert to units of seconds per megabyte */
4660 this_alloc_rate = alloc_elapsed * 1.0e6 / ((time_flt) tc_alloced);
4661 g_ttl_elapsed += this_alloc_rate;
4662
4663 /* Determine the timebase we should use for our decaying averages: Short
4664 halflife at first, then longer. */
4665 if (mem_used_KiB < 20480) {
4666 decay_numer = 0.9;
4667 } else {
4668 decay_numer = 0.993;
4669 }
4670 decay_denom = 1.0 - decay_numer;
4671
4672
4673 /* Decaying average with half-life of roughly 100 samples:
4674 0.5 ^ 0.01 = 0.993092... */
4675 if (g_avg_alloc_rate == 0) {
4676 g_avg_alloc_rate = this_alloc_rate;
4677 } else {
4678 g_avg_alloc_rate = (decay_numer * g_avg_alloc_rate)
4679 + (decay_denom * this_alloc_rate);
4680 }
4681 if (this_alloc_rate < g_avg_alloc_rate) {
4682 /* This sample brought down the average, so it should be counted
4683 towards the "good performance level" statistic. */
4684 if (g_good_alloc_rate == 0) {
4685 g_good_alloc_rate = this_alloc_rate;
4686 } else {
4687 g_good_alloc_rate = (decay_numer * g_good_alloc_rate)
4688 + (decay_denom * this_alloc_rate);
4689 }
4690 }
4691
4692 rate_where = mem_used_KiB;
4693
4694 /* Find out how many times exec() was called, which is a good measure of
4695 how much computation we've done and therefore how much time "should
4696 have" elapsed */
4697 predicted_rate = (((time_flt) g_exec_calls) + 1.0) / 4.0e6
4698 + (((time_flt) g_cv_calls) + 1.0) / 2.5e6;
4699
4700 /* From the prediction and the actual elapsed time, make a measure of
4701 sluggishness. */
4702 sluggish_ratio = g_ttl_elapsed / predicted_rate;
4703
4704 if (debug_M) {
4705 printf(
4706 "%4ld MiB, ex%8ld, cv%7ld: %6.3g/%6.3g = %6.3g",
4707 ((mem_used_KiB >> 9) + 1) >> 1,
4708 g_exec_calls, g_cv_calls,
4709 g_ttl_elapsed, predicted_rate, sluggish_ratio);
4710 }
4711
4712 /* Reset the raw counters for the next sample */
4713 g_cv_calls = 0;
4714 g_exec_calls = 0;
4715 g_ttl_elapsed = 0;
4716
4717 /* Count how many times in a row the new sample is bigger than the
4718 decaying average */
4719 if (sluggish_ratio > g_decay_slug * g_mem_bad_ratio) {
4720 if (debug_M) { printf(" >%6.3g", g_decay_slug); }
4721 g_rate_increase_run++;
4722 } else {
4723 if (debug_M) { printf(" %6s", ""); }
4724 g_rate_increase_run = 0;
4725 }
4726 /* g_max_rir keeps track of the longest "run" since the last time
4727 g_max_rir was reset */
4728 if (g_rate_increase_run > g_max_rir) {
4729 g_max_rir = g_rate_increase_run;
4730 }
4731 /* Keep a bitmap of the history of recent extreme incidents */
4732 if (sluggish_ratio > g_decay_slug * g_mem_bad_ratio) {
4733 g_last_thrash |= 1;
4734 }
4735 g_last_thrash <<= 1;
4736 g_last_thrash &= ((1 << 10) - 1);
4737
4738 /* Decay-average the slug ratio */
4739 if (g_decay_slug == 0) {
4740 g_decay_slug = sluggish_ratio;
4741 } else {
4742 g_decay_slug = (decay_numer * g_decay_slug)
4743 + (decay_denom * sluggish_ratio);
4744 }
4745
4746 if (mem_used_KiB >= memstat_where + 10240) {
4747 /* It's time to look at the stats and make a guess */
4748
4749 if (debug_M) {
4750 /* To evaluate these measurements, run RIES in different memory
4751 / environments using a command like:
4752 / ries 2.50631415926535897932 -l8 -DM */
4753 printf(" avg %6.3g", g_decay_slug);
4754 printf(", run %ld", g_max_rir); g_max_rir = 0;
4755 printf(" (%6.3g ; %6.3g sec/MB)", g_avg_alloc_rate, g_good_alloc_rate);
4756
4757 if (((time_flt)mem_used_KiB) * 1024.0 > g_min_memory) {
4758 /* Here we would check for a "getting really slow" trend and quit
4759 if it is exceeded */
4760 if (bitcount(g_last_thrash) >= 3) {
4761 /* Okay, pull the plug. */
4762 printf("\nExiting now because memory has gotten very slow.\n");
4763 print_end(EXIT_NO_ERROR);
4764 }
4765 }
4766 }
4767 fflush(stdout);
4768 memstat_when = now;
4769 memstat_where = mem_used_KiB;
4770 }
4771 if (debug_M) { printf("\n"); }
4772
4773 tc_alloced = 0;
4774} /* End of thrash.check */
4775
4776void init_mem(void)
4777{
4778 freepool = 0;
4779 freesize = 0;
4780 block_base = 0;
4781 mem_used_KiB = 0;
4782 mem_used_bytes = 0;
4783}
4784
4785/* All allocation is done in fixed-size blocks, and nothing is ever
4786 * deallocated, so it's very easy to manage. This is your typical
4787 * cached blocked allocate funtion */
4788void * my_alloc(size_t size)
4789{
4790 s16 do_alloc;
4791 char * rv;
4792
4793 /* assume the worst */
4794 rv = 0;
4795
4796 /* first, see if there's a block with enough space */
4797 do_alloc = 0;
4798 if (freepool) {
4799 if (freesize >= size) {
4800 /* we're okay */
4801 } else {
4802 do_alloc = 1;
4803 }
4804 } else {
4805 do_alloc = 1;
4806 }
4807
4808 /* if we need to allocate, do so */
4809 if (do_alloc) {
4810 freesize = 0;
4811 freepool = (char *) malloc(ALLOC_SIZE);
4812
4813 /* did we get any? */
4814 if (freepool) {
4815 freesize = ALLOC_SIZE;
4816 mem_used_KiB += (ALLOC_SIZE / 1024L);
4817 }
4818
4819 thrash_check(ALLOC_SIZE);
4820
4821 if (((time_flt)mem_used_KiB) * 1024.0 > g_max_memory) {
4822 printf("Stopping now because %g bytes of memory have been used.\n",
4823 ((time_flt)mem_used_KiB) * 1024.0);
4824 print_end(EXIT_NO_ERROR);
4825 }
4826
4827 /* Immediately make our new block point to the previous block, if there
4828 was any. This is to support purgeall_mem(). */
4829 if (freepool) {
4830 *((char * *)freepool) = block_base; /* Store backlink ptr */
4831 block_base = freepool; /* This is the new base ptr */
4832 freepool += sizeof(char *); /* This is where the user's data will
4833 be allocated */
4834 freesize -= sizeof(char *); /* We used up some space */
4835 /* Carefully track memory usage */
4836 mem_used_bytes += sizeof(char *);
4837 }
4838 }
4839
4840 /* if we have a block now, we can allocate from it */
4841 if (freepool) {
4842 rv = freepool;
4843 freepool += size; /* %%% how do I find out the alignment
4844 requirement for pointers to structs? */
4845 freesize -= size;
4846 /* Carefully track memory usage */
4847 mem_used_bytes += size;
4848 }
4849
4850 return((void *) rv);
4851} /* End of my.alloc() */
4852
4853/* I said above that "nothing is ever deallocated", but here you can
4854 deallocate everything all at once if you wish.
4855 %%% NOTE: As of 20160131, this is still not used; the plan is to facilitate
4856 running searches against multiple targets and avoid some of the duplicated
4857 recalculation. */
4858void purgeall_mem(void)
4859{
4860 char * prev_block;
4861 while(block_base) {
4862 prev_block = *((char * *) block_base);
4863 free((void *) block_base);
4864 block_base = prev_block;
4865 }
4866}
4867
4868/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4869
4870 Metastack routines (see the "M E T A S T A C K !" block comment above)
4871
4872 The following illustrate the contents of the stack and undo
4873 list for some sample expressions. The expressions read from top
4874 to bottom, and there is one line for each push or pop. (There
4875 are no undo's illustrated here; an undo would be just moving up
4876 to a previous line). At the end of each example is the total
4877 number of steps: This is the number of items in the undo list.
4878
4879 expression: 1+(2+(4+8)) expression: sqrt(sqrt((2^2)^2)^2)^2
4880 postfix: 1248+++ postfix: 2ssqsqs
4881 op stack --undo-stack-- op stack --undo-stack--
4882 1 1 2 2
4883 2 1 2 s - 2
4884 4 1 2 4 4 2
4885 8 1 2 4 8 s - 2 4
4886 + 1 2 4 8 16 2 4
4887 1 2 8 4 q - 2 4 16
4888 1 2 12 8 4 4 2 4 16
4889 + 1 2 8 4 12 s - 2 4 16 4
4890 1 8 4 12 2 16 2 4 16 4
4891 1 14 8 4 12 2 q - 2 4 16 4 16
4892 + 1 8 4 12 2 14 4 2 4 16 4 16
4893 - 8 4 12 2 14 1 s - 2 4 16 4 16 4
4894 15 8 4 12 2 14 1 16 2 4 16 4 16 4
4895 total steps: 13 total steps: 13
4896 max stack: 4 max stack: 1
4897 max undo stack: 6 max undo stack: 6
4898
4899 expression: 1/(3-1/(-2))
4900 postfix: 11nr-r
4901 op stack --undo-stack--
4902 3 3
4903 2 3 2
4904 n 3 2
4905 3 -2 2
4906 r 3 2 -2
4907 3 -0.5 2 -2
4908 - 3 2 -2 -0.5
4909 - 2 -2 -0.5 3
4910 3.5 2 -2 -0.5 3
4911 r - 2 -2 -0.5 3 3.5
4912 0.286 2 -2 -0.5 3 3.5
4913 total steps: 11
4914 max stack: 2
4915 max undo stack: 5
4916_____________________________________________________________________________*/
4917
4918void ms_init(metastack *ms)
4919{
4920 ms->uvp = 0;
4921 ms->msp = 0;
4922 ms->sp = 0;
4923}
4924
4925#define dbl(x) ((double)(x))
4926
4927/* ms.push does a standard PUSH operation. */
4928void ms_push(metastack *ms, ries_val x, ries_dif dx, ries_tgs tags)
4929{
4930 s16 sp, msp;
4931
4932 /* push x */
4933 sp = ms->sp;
4934
4935 (ms->ds)[sp] = dx;
4936 (ms->s)[sp] = x;
4937 (ms->tg)[sp] = tags;
4938
4939 /* remember */
4940 msp = ms->msp;
4941 ms->ms[msp] = MSO_PUSH;
4942
4943 if (debug_m) {
4944 printf("push %d %g (%g)%x '%d'\n", sp, dbl(x), dx, tags, msp);
4945 }
4946
4947 /* for a push, we don't need to add any undo values */
4948
4949 sp++;
4950 ms->sp = sp;
4951 msp++;
4952 ms->msp = msp;
4953}
4954
4955/* ms_pop does a standard POP operation. */
4956ries_val ms_pop(metastack *ms, ries_dif *diff, ries_tgs * tags)
4957{
4958 s16 sp, msp, uvp;
4959 ries_val rv;
4960 ries_dif drv;
4961 ries_tgs tg;
4962
4963 /* pop a value */
4964 sp = ms->sp;
4965 sp--;
4966 rv = (ms->s)[sp];
4967 drv = (ms->ds)[sp];
4968 if (diff) {
4969 *diff = drv;
4970 }
4971 tg = (ms->tg)[sp];
4972 if (tags) {
4973 *tags = tg;
4974 }
4975 ms->sp = sp;
4976
4977 /* remember the action and the data */
4978 msp = ms->msp;
4979 ms->ms[msp] = MSO_POP;
4980
4981 /* save the popped values in the undo list */
4982 uvp = ms->uvp;
4983 if (debug_m) {
4984 printf("pop %d %g (%g)%x '%d' .%d.\n", sp, dbl(rv), drv, tg, msp, uvp);
4985 }
4986 ms->udv[uvp] = drv;
4987 ms->uv[uvp] = rv;
4988 ms->utg[uvp] = tg;
4989
4990 msp++;
4991 ms->msp = msp;
4992 uvp++;
4993 ms->uvp = uvp;
4994
4995 return rv;
4996}
4997
4998/* ms_peek just lets you see what's on the top of the stack. */
4999ries_val ms_peek(metastack *ms, ries_dif *diff, ries_tgs * tag, s16 *sptr)
5000{
5001 s16 sp;
5002 ries_val rv;
5003 ries_dif drv;
5004 ries_tgs tg;
5005
5006 sp = (s16)((ms->sp)-1);
5007 rv = ms->s[sp];
5008 drv = ms->ds[sp];
5009 if (diff) {
5010 *diff = drv;
5011 }
5012 tg = ms->tg[sp];
5013 if (tag) {
5014 *tag = tg;
5015 }
5016 if (sptr) {
5017 *sptr = sp;
5018 }
5019 if (debug_m) {
5020 printf("peek %d %g (%g)%x\n", sp, dbl(rv), drv, tg);
5021 }
5022 return (rv);
5023}
5024
5025/* ms_undo performs a metastack UNDO operation -- it returns the stack to the
5026 state it was in before the most recent PUSH or POP. */
5027void ms_undo(metastack *ms)
5028{
5029 s16 msp, opcode;
5030
5031 /* pop the opcode */
5032 msp = ms->msp;
5033 opcode = ms->ms[--msp];
5034 ms->msp = msp;
5035
5036 if (opcode == MSO_PUSH) {
5037 /* to undo a PUSH is easy -- just pop the SP. */
5038 ms->sp--;
5039 if (debug_m) { printf("undo-push\n"); }
5040 } else {
5041 s16 uvp, sp;
5042 ries_val uv;
5043 ries_dif udv;
5044 ries_tgs tg;
5045 /* undo a POP. This is like a PUSH except we have to retrieve the value
5046 from the undo data. */
5047 uvp = ms->uvp;
5048 uvp--;
5049 uv = ms->uv[uvp];
5050 udv = ms->udv[uvp];
5051 tg = ms->utg[uvp];
5052 ms->uvp = uvp;
5053
5054 sp = ms->sp;
5055 ms->ds[sp] = udv;
5056 ms->s[sp] = uv;
5057 ms->tg[sp] = tg;
5058 sp++;
5059 ms->sp = sp;
5060 if (debug_m) { printf("undo-pop\n"); }
5061 }
5062}
5063
5064/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5065
5066Sources and notes related to special functions and their algorithms.
5067%%% Most of this will/should be moved into msal_math64.c, f107_o.cpp
5068and/or msal_math128.c
5069
5070Sources:
5071 msal_math64.c already contains sin/cos/tan from Sun via Netlib,
5072 and my own sinl/cosl/tanl.
5073
5074 I have the openlibm sources, which include a fairly readable 80-bit ldbl
5075 mathlib, at ~/devt/julia/openlibm on SB4
5076
5077 .../libs/f107_o/f107_o.cpp already contains all the "normal" functions
5078 in high-precision: sqrt, sin, cos, exp, log, sinh, etc.
5079
5080 Lambert W is already in msal_math64.c (derived from Veberic, "Having
5081 Fun with Lambert W(x) Function", 2009
5082 A much more thorough approach, with about 20 different polynomial fits
5083 and both branches, is in .../ries/LambertW-darko
5084
5085 .../zeta/zeta.cpp contains the high-precision Gamma function (but no
5086 corresponding digamma, however the single-precision digamma will probably
5087 be good enough)
5088
5089 I have the Boost C++ Libraries (from www.boost.org); the C source code
5090 is in "boost_1_53_0.tar.bz2". Most of the code of interest is in
5091 "boost/math/special_functions", e.g. their Lanczos Gamma is in files
5092 .../special_functions/gamma.hpp and .../special_functions/lanczos.hpp
5093
5094 The GNU Scientific Library (GSL) has a lot of special functions that
5095 look reasonably easy to adapt. See notes in .../ries/0-notes.txt ; and
5096 source code in devt/gcc45/tars/gsl-1.15/specfunc and in gsl-1.16.tar.gz
5097
5098 I also have the GNU version of the C libraries (which includes the more
5099 common functions like exp and tan) in glibc-2.20.tar.gz but a lot of
5100 the code is in assembler. See libm_sincosl.S for example. There is also
5101 some code that is in C, such as sysdeps/ieee754/ldbl-96/k_cosl.c and
5102 .../ldbl-96/t_sincosl.c for the "96-bit" long double version of cosine.
5103 And oddly there is "multi-precision" code, e.g. see sincos32.c and
5104 mpa.c in .../ieee754/dbl-64 which uses radix-2^24 maths and apparently
5105 a Taylor series (see .../ieee754/dbl-64/dosincos.c) and some double-double
5106 arithmetic in the style of Dekker 1971 (see .../ieee754/dbl-64/dla.h)
5107 all for the purpose of getting a correctly-rounded result (see
5108 .../ieee754/dbl-64/s_sin.c)
5109
5110 Cody, William J., Jr., and Waite, William. Software Manual for the
5111 Elementary Functions. Prentice-Hall (Englewood Cliffs, New Jersey, 1980).
5112
5113Constants that may also be useful (these could be provided to users as
5114a built-in profile, or at least listed on the website). I am giving
5115only 35 decimal digits, as that's all we'd need for f107 precision:
5116
51170.56714329040978387299996866221035554
5118 The "omega" constant W(1), with the property : omega e^omega = 1.
5119See OEIS[A30178].
5120
51210.57721566490153286060651209008240243
5122 Euler's constant "gamma", -Digamma(1), OEIS[A1620].
5123
51241.2020569031595942853997381615114499
5125 Apery's constant Zeta(3), OEIS[A2117]. e^gamma is also somewhat important.
5126
51272.5029078750958928222839028732182157
5128 Feigenbaum reduction parameter, OEIS[6891].
5129
51304.6692016091029906718532038204662016
5131 Feigenbaum bifurcation velocity, OEIS[6890].
5132
5133_____________________________________________________________________________*/
5134
5135#if 0
5136/* the man page for atan2 doesn't specify its behavior when both arguments
5137 are zero, so just to be safe I am defining it myself. */
5138double arctan(double a, double b)
5139{
5140 double rv;
5141
5142 if ((a == k_0) && (b == k_0)) {
5143 rv = k_0;
5144 } else {
5145 rv = atan2(a,b);
5146 }
5147 return rv;
5148}
5149
5150long double arctanl(long double a, long double b)
5151{
5152 long double rv;
5153
5154 if ((a == k_0) && (b == k_0)) {
5155 rv = k_0;
5156 } else {
5157 rv = atan2l(a,b);
5158 }
5159 return rv;
5160}
5161#endif
5162
5163/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5164
5165Notes on transcendental functions:
5166
5167 sinh
5168 sinh(x) = (e^x - e^-x) / 2
5169
5170 complex natural logarithm
5171 cln(z) = ln(cabs(z)) + phase(z) i
5172
5173 complex exponential
5174 cexp(z) = exp(a) (cos b + i sin b)
5175
5176 complex sine (and sinh)
5177 csin(z) = (cexp(i z) - cexp(-i z)) / 2i
5178 csin(i z) == i csinh(z)
5179
5180 csin(z) = (cexp(i z) - cexp(-i z)) / 2i
5181 = (cexp(ai - b) - cexp(b - ai)) / 2i
5182 = (e^-b (cos a + i sin a) - e^b (cos a - i sin a)) / 2i
5183 = (e^-b cos a + i e^-b sin a - e^b cos a + i e^b sin a) / 2i
5184 = i 1/2 e^-b cos a - 1/2 e^-b sin a - i 1/2 e^b cos a - 1/2 e^b sin a
5185 a + bi = i 1/2 e^-b cos a - 1/2 e^-b sin a - i 1/2 e^b cos a - 1/2 e^b sin a
5186
5187 a = - 1/2 e^-b sin a - 1/2 e^b sin a
5188 bi = i 1/2 e^-b cos a - i 1/2 e^b cos a
5189
5190 a = - 1/2 e^-b sin a - 1/2 e^b sin a = - sin a cosh b
5191 b = 1/2 e^-b cos a - 1/2 e^b cos a = - cos a sinh b
5192
5193 b = - cos a (e^b - e^-b)/2
5194 b 2 / (e^-b - e^b) = - cos a
5195 -2 b / (e^-b - e^b) = cos a
5196 2 b / (e^b - e^-b) = cos a
5197 a = 2 pi K + cos' (2 b / (e^b - e^-b))
5198
5199 a = - sin a (e^b + e^-b)/2
5200 -1 = sin(a)/a (e^b + e^-b)/2
5201 -2/(e^b + e^-b) = sin(a)/a
5202 - bell(b) = sin(a)/a
5203 b = +/- bell' (-sin(a)/a) [defined only when sin(a)/a < 0]
5204
5205 +/- bell'(-sin(a)/a) = - cos a sinh(+/- bell'(sin(a)/a))
5206
5207 2 pi K + cos' (2 b / (e^b - e^-b)) = - cosh b sqrt(1 - (2 b / (e^b - e^-b))^2)
5208
5209
5210
5211 More elaborate functions follow. These are the ones that do not
5212 come directly out of the closure of the simple operators + - * / ^ v
5213 (as is the case for log, exp, sin and cos and their related functions)
5214 but from new concepts such as the integral of a function, etc.
5215 This includes the standard distribution, the Gamma function,
5216 Bessel functions, etc.
5217
5218
5219Gamma function and generalized factorial: most notes and source
5220have now been moved to msal_math64.c
5221
5222
5223 binomial coefficients
5224 The binomial coefficient "n over k" is:
5225
5226 bincoef(n,k) = n! / ((n-k)! k!)
5227 = exp(lngamma(n) - (lngamma(n-k) + lngamma(k)))
5228
5229
5230Riemann Zeta function: see the implementation in .../zeta/ken-takusagawa
5231
5232
5233Jacobi elliptic functions:
5234 Jacobi amplitude am(u,k) inverse of the Elliptic Integral of the First Kind
5235 (in MMa: JacobiAmplitude[u, k^2])
5236 sn(u, k) = sin(am(u, k))
5237 cn(u, k) = cos(am(u, k))
5238 dn(u, k) = = sqrt(1-(k sn(u,k))^2) = d/du am(u, k)
5239
5240 Two versions are in function-sources.txt; see also:
5241 http://en.wikipedia.org/wiki/Theta_function
5242 http://code.google.com/p/elliptic/source/browse/trunk/ellipj.m
5243 http://sourceforge.net/projects/asymptote/forums/forum/409349/topic/4725092
5244
5245 */
5246
5247/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5248
5249 exec() contains all the code that actually performs computations on
5250 subexpressions during the RIES search.
5251
5252_____________________________________________________________________________*/
5253
5254/* exec actually executes an opcode, using a metastack. It returns a
5255 nonzero value if there was an error, e.g. divide-by-zero. It also
5256 sets undo_count to a number indicating the number of times you have to
5257 call ms_undo to put the stack back to the state it was in before calling
5258 exec on this opcode.
5259
5260There is plenty of error checking for zero and negative arguments, but
5261no checking for overflow. The reason is that only a few expressions,
5262(the simplest is 445^^) are capable of overflowing -- so it is not
5263much of an optimization. There is no danger of the program generating
5264an exception from overflow.
5265
5266If the symbol is 'x', the value of exec.x is placed on the stack.
5267Normally (as when exec() is called by ge.2 or canon.val) this is the
5268target value, but when called by eval() for newton() or the
5269--eval-expression command it might be set to another value.
5270 */
5271s16 exec(metastack *ms, symbol op, s16 *undo_count, s16 do_dx)
5272{
5273 ries_val a = 0; /* Argument 1 */
5274 ries_val b = 0; /* Argument 2 */
5275 ries_val lb; /* Log of b */
5276 ries_val rv; /* Return value */
5277 ries_dif da = 0;/* Derivatives */
5278 ries_dif db = 0;
5279 ries_dif drv;
5280 ries_tgs tga; /* Tags of arg 1 */
5281 ries_tgs tgb; /* Tags of arg 2 */
5282 ries_tgs trv; /* Tags of result */
5283 int f1; /* flag */
5284
5285 /* set default for derivative (overridden if we compute it) */
5286 drv = (ries_dif)k_0;
5287 tga = tgb = trv = TYPE_NONE;
5288
5289 switch(op) {
5290 /* seft '0' ( -- ) symbols. These do nothing. */
5291 case ' ' :
5292 rv = 0; *undo_count = 0; break; /* ' ' is a no-op */
5293
5294 /* Roll '(' or ')' operators might go here */
5295
5296 /* seft 'a' ( -- K ) symbols. For all constants the derivative is zero;
5297 for X the derivative is 1.0 */
5298 case '1' :
5299 rv = k_1; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5300 case 'f' :
5301 rv = k_phi; ms_push(ms, rv, (ries_dif) k_0, tg_phi); *undo_count = 1; break;
5302 case '2' :
5303 rv = k_2; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5304 case 'e' :
5305 rv = k_e; ms_push(ms, rv, (ries_dif) k_0, tg_e); *undo_count = 1; break;
5306 case '3' :
5307 rv = k_3; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5308 case 'p' :
5309 rv = k_pi; ms_push(ms, rv, (ries_dif) k_0, tg_pi); *undo_count = 1; break;
5310 case '4' :
5311 rv = k_4; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5312 case '5' :
5313 rv = k_5; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5314 case '6' :
5315 rv = k_6; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5316 case '7' :
5317 rv = k_7; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5318 case '8' :
5319 rv = k_8; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5320 case '9' :
5321 rv = k_9; ms_push(ms, rv, (ries_dif) k_0, TYPE_INT); *undo_count = 1; break;
5322
5323 case 'x' :
5324 rv = exec_x; drv = (ries_dif) k_1;
5325 ms_push(ms, rv, drv, g_targ_tags); *undo_count = 1; break;
5326
5327 /* seft 'b' ( arg -- val ) symbols */
5328 case 'I' : /* Identity: used only when all other seft-b symbols
5329 have been excluded */
5330 a = ms_pop(ms, &da, &tga);
5331 rv = a;
5332 drv = da;
5333 trv = tga;
5334 ms_push(ms, rv, drv, trv); *undo_count = 2;
5335 break;
5336
5337 case 'n' : /* negate */
5338 /* n(a+bi) = -a + -bi */
5339 a = ms_pop(ms, &da, &tga);
5340 if (do_dx) {
5341 drv = - da;
5342 }
5343 rv = -a;
5344 trv = tga;
5345 ms_push(ms, rv, drv, trv); *undo_count = 2;
5346 break;
5347
5348 case 'r' : /* reciprocal */
5349 /* r(a+bi) = (a-bi) / (a^2 + b^2) */
5350 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5351 if (a == k_0) {
5352 return ERR_EXEC_DIV_ZERO;
5353 }
5354 if (do_dx) {
5355 drv = (ries_dif) (( - da) / (a * a));
5356 }
5357 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5358 return ERR_EXEC_ILLEGAL_DERIV;
5359 }
5360 rv = k_1 / a;
5361 /* Int become rational, everything else stays the same */
5362 trv = TGMIN(tga, TYPE_RAT); /* tgs-manip */
5363 ms_push(ms, rv, drv, trv); *undo_count = 2;
5364 break;
5365
5366 case 's' : /* squared */
5367 a = ms_pop(ms, &da, &tga);
5368 if (do_dx) {
5369 drv = (ries_dif) (k_2 * a * da);
5370 }
5371 rv = a * a;
5372 trv = tga;
5373 ms_push(ms, rv, drv, trv); *undo_count = 2;
5374 break;
5375
5376 case 'q' : /* square root */
5377 /* q(a+bi) is the conjugate with the same imaginary sign as bi.
5378 for example, q(i) = (1+i)/sqrt(2); q(-i) = (1-i)/sqrt(2) */
5379 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5380 if (a < k_0) {
5381 return ERR_EXEC_ROOT_NEG;
5382 }
5383 rv = SQRT(a);
5384 if (do_dx) {
5385 drv = (ries_dif) (da / (k_2 * rv));
5386 }
5387 /* tgs-manip: Try to determine if it was a perfect square and tag result
5388 accordingly. This happens if target is 143 and we're computing [x1-q] */
5389 if ( (tga == TYPE_INT)
5390 && (rv < 1.0e6)
5391 && (rv == FLOOR(rv))) {
5392 trv = TYPE_INT;
5393 } else {
5394 trv = TGMIN(TYPE_CONS, tga);
5395 }
5396 ms_push(ms, rv, drv, trv); *undo_count = 2;
5397 break;
5398
5399 case 'l' : /* ln */
5400 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5401 if (g_restrict_exponents) {
5402 if ((da != 0) /* a is a subexpression containing x */
5403 || (tga < g_restrict_exponents)) {
5404 return ERR_EXEC_ILLEGAL_EXPONENT;
5405 }
5406 }
5407 if (a <= k_0) {
5408 return ERR_EXEC_LOG_NEG;
5409 }
5410 if (FABS(a - 1.0) <= k_sig_loss) {
5411 /* Loss-of-significance error. For example ln(1.00023)=2.3e-4.
5412 The input 1.00023 has 6 significant figures but the value
5413 2.3e-4 only has 2. */
5414 return ERR_EXEC_SIG_LOSS;
5415 }
5416 if (do_dx) {
5417 drv = (ries_dif) (da / a);
5418 }
5419 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5420 return ERR_EXEC_ILLEGAL_DERIV;
5421 }
5422 rv = LOG(a);
5423 trv = TGMIN(tga, TYPE_ELEM); /* tgs-manip */
5424 ms_push(ms, rv, drv, trv); *undo_count = 2;
5425 break;
5426
5427 case 'E' : /* e ^ X */
5428 /* E(a+bi) = e^x (cos b + sin b i) */
5429 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5430 if (g_restrict_exponents) {
5431 if ((da != 0) /* a is a subexpression containing x */
5432 || (tga < g_restrict_exponents)) {
5433 return ERR_EXEC_ILLEGAL_EXPONENT;
5434 }
5435 }
5436 if (a > k_eXlim) {
5437 return ERR_EXEC_OVERFLOW;
5438 }
5439 if (a < k_sig_loss) {
5440 /* Loss-of-significance error, e.g. "e^0.0001" */
5441 return ERR_EXEC_SIG_LOSS;
5442 }
5443 rv = EXP(a);
5444 if (do_dx) {
5445 drv = (ries_dif) (rv * da);
5446 }
5447 trv = TGMIN(tga, TYPE_ELEM); /* tgs-manip */
5448 ms_push(ms, rv, drv, trv); *undo_count = 2;
5449 break;
5450
5451 case 'S' : /* sine */
5452 /* d/dx sin(u) = cos(u) */
5453 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5454 if (g_restrict_trig_args) {
5455 if ((da != 0) /* a is a subexpression containing x */
5456 || (tga < g_restrict_trig_args)) {
5457 return ERR_EXEC_TRIG_ARGTYPE;
5458 }
5459 }
5460 a *= k_sincos_arg_scale;
5461 if ((a >= k_pi) || (-a >= k_pi)) {
5462 /* This is to eliminate nonsense "solutions" like "sin(X^9) = 1/4" */
5463 return ERR_EXEC_TRIG_RANGE;
5464 }
5465 rv = SIN(a);
5466 if (FABS(rv) > k_sin_clip) {
5467 /* This is to eliminate stuff like "sin(pi/2 + 0.00001) = 1"
5468 %%% This is partly redundant with testing dx < k_vanished.dx.
5469 If x=pi/2+0.00001 then the derivative will be really small and
5470 it's a meaningless solution. On the other hand, sin(pi/2 + 0.00001)
5471 itself is sufficiently precise (there is no loss of significant
5472 figures) and might be of interest. */
5473 return ERR_EXEC_TRIG_LOW_DX;
5474 }
5475 if (FABS(COS(a)) < k_sig_loss) {
5476 /* Significance is lost when the value of sin is near +- 1 */
5477 return ERR_EXEC_SIG_LOSS;
5478 }
5479 if (FABS(rv) < (FABS(a) * k_sig_loss)) {
5480 /* Loss-of-significance error, e.g. "sin(pi+0.0001)" */
5481 return ERR_EXEC_SIG_LOSS;
5482 }
5483 if (do_dx) {
5484 drv = (ries_dif) (COS(a) * k_sincos_arg_scale * da);
5485 if (FABS(drv) < (FABS(da) * k_sig_loss)) {
5486 return ERR_EXEC_SIG_LOSS;
5487 }
5488 }
5489 /* tgs-manip: if k_sincos_arg_scale is pi, rational arg -> algebraic */
5490 if (g_trig_scale_default) {
5491 trv = (tga >= TYPE_RAT) ? TYPE_ALG : TYPE_NONE;
5492 } else {
5493 trv = TYPE_NONE;
5494 }
5495 ms_push(ms, rv, drv, trv); *undo_count = 2;
5496 break;
5497
5498 case 'C' : /* cosine */
5499 /* d/dx cos(u) = - sin(u) */
5500 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5501 if (g_restrict_trig_args) {
5502 if ((da != 0) /* a is a subexpression containing x */
5503 || (tga < g_restrict_trig_args)) {
5504 return ERR_EXEC_TRIG_ARGTYPE;
5505 }
5506 }
5507 a *= k_sincos_arg_scale;
5508 if ((a >= k_pi) || (-a >= k_pi)) {
5509 /* This is to eliminate nonsense "solutions" like "sin(X^9) = 1/4" */
5510 return ERR_EXEC_TRIG_RANGE;
5511 }
5512 rv = COS(a);
5513 if (FABS(rv) < (FABS(a) * k_sig_loss)) {
5514 /* Loss-of-significance error, e.g. "cos(pi/2.0001)" */
5515 return ERR_EXEC_SIG_LOSS;
5516 }
5517 if (FABS(SIN(a)) < k_sig_loss) {
5518 /* Significance is lost when the value of cos is near +- 1 */
5519 return ERR_EXEC_SIG_LOSS;
5520 }
5521 if (FABS(rv) > k_sin_clip) {
5522 /* This is to eliminate stuff like "cos(0.00001) = 1" */
5523 return ERR_EXEC_TRIG_LOW_DX;
5524 }
5525 if (do_dx) {
5526 drv = (ries_dif) (k_0 - (SIN(a) * k_sincos_arg_scale * da));
5527 }
5528 /* tgs-manip: if k_sincos_arg_scale is pi, rational arg -> algebraic */
5529 if (g_trig_scale_default) {
5530 trv = (tga >= TYPE_RAT) ? TYPE_ALG : TYPE_NONE;
5531 } else {
5532 trv = TYPE_NONE;
5533 }
5534 ms_push(ms, rv, drv, trv); *undo_count = 2;
5535 break;
5536
5537 case 'T' : /* tangent */
5538 /* d/dx tan(u) = (1 + tan^2(u)) du */
5539 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5540 if (g_restrict_trig_args) {
5541 if ((da != 0) /* a is a subexpression containing x */
5542 || (tga < g_restrict_trig_args)) {
5543 return ERR_EXEC_TRIG_ARGTYPE;
5544 }
5545 }
5546 a *= k_sincos_arg_scale;
5547 if ((a >= k_pi) || (-a >= k_pi)) {
5548 /* This is to eliminate nonsense "solutions" like "tan(X^9) = 1/4" */
5549 return ERR_EXEC_TRIG_RANGE;
5550 }
5551 rv = TAN(a);
5552 if (FABS(rv) > (1 / k_sig_loss)) {
5553 /* Loss-of-significance error, e.g. "tan(pi/2.0001)" */
5554 return ERR_EXEC_SIG_LOSS;
5555 }
5556 if ((a!=0) && (FABS(rv/a) < k_sig_loss)) {
5557 /* Significance is lost when the value of tangent is near zero
5558 (except when the argument is also near zero) */
5559 return ERR_EXEC_SIG_LOSS;
5560 }
5561 if (do_dx) {
5562 drv = (ries_dif) (k_sincos_arg_scale * (1.0 + rv*rv) * da);
5563 }
5564 /* tgs-manip: if k_sincos_arg_scale is pi, rational arg -> algebraic */
5565 if (g_trig_scale_default) {
5566 trv = (tga >= TYPE_RAT) ? TYPE_ALG : TYPE_NONE;
5567 } else {
5568 trv = TYPE_NONE;
5569 }
5570 ms_push(ms, rv, drv, trv); *undo_count = 2;
5571 break;
5572
5573 /* 'G' Gamma function would go here */
5574
5575 case 'W': /* Lambert W function */
5576 a = ms_pop(ms, &da, &tga); *undo_count = 1;
5577 if (a < k_ern) {
5578 /* If x is less than -1/e, W(x) has complex values. This is kind of like
5579 taking the logarithm of a negative number, so we'll use that error. */
5580 return ERR_EXEC_LOG_NEG;
5581 }
5582 rv = LAMBERTW(a);
5583 if (do_dx) {
5584 if (rv <= -1.0) {
5585 /* At W(x) = -1 the derivative is undefined (infinite) and if we get
5586 W(x) < -1 there was roundoff error in evaluating W(x) */
5587 return ERR_EXEC_ILLEGAL_DERIV;
5588 } else if (FABS(a) < 1.0e-30) {
5589 /* The derivative calculation involves "W(x)/x" which approaches 1 as x
5590 approaches 0 and involves loss of precision, but that's not a
5591 problem. However when x gets very small we might have underflow,
5592 and when it is exactly 0 we need to avoid the division. We do this
5593 by removing "rv" from the numerator and "a" from the denominator. */
5594 drv = (ries_dif) (da / (rv + 1.0));
5595 } else {
5596 drv = (ries_dif) (da * rv / (a * (rv + 1.0)));
5597 }
5598 }
5599 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5600 return ERR_EXEC_ILLEGAL_DERIV;
5601 }
5602 /* Values of W(x) are considered "transcendental" */
5603 trv = TGMIN(tga, TYPE_TRAN); /* tgs-manip */
5604 ms_push(ms, rv, drv, trv); *undo_count = 2;
5605 break;
5606
5607 /* seft 'c' ( arg1 arg2 -- val ) symbols */
5608 case '-' :
5609 b = ms_pop(ms, &db, &tgb);
5610 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5611 /* this operator shares the loss-of-significance tests with '+' */
5612 b = - b; db = - db;
5613 goto add_common;
5614
5615 case '+' :
5616 b = ms_pop(ms, &db, &tgb);
5617 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5618 add_common: ;
5619 rv = a + b;
5620 if ((FABS(a) < (FABS(b) * k_sig_loss))
5621 || (FABS(b) < (FABS(a) * k_sig_loss)) ) {
5622 /* loss-of-significance error, e.g. "1 + e^(5^2)"
5623 In addition to the risk of meaningless tautologies like
5624 "x^2 = 2" followed by "x^2+e^(e^pi) = e^(e^pi)+2",
5625 this test is also useful for pruning: the expression
5626 "1 + e^(5^2)" is useless to us because there is no way to
5627 distinguish it from the simpler expression "e^(5^2)" */
5628 /* 20120505: If (a+b)-b == a, then no information has been lost,
5629 so we allow the operation to be performed. This is very important
5630 for -i (integer subexpressions) when x>100. */
5631 if (((rv - b) != a) || ((rv - a) != b)) {
5632 return ERR_EXEC_SIG_LOSS;
5633 }
5634 }
5635 if ((FABS(rv) < (FABS(a) * k_sig_loss))
5636 || (FABS(rv) < (FABS(b) * k_sig_loss)) ) {
5637 /* another loss-of-significance error, e.g. "1e40 - (1e40+1)" */
5638 /* 20120505: Similarly, when a sum is of lesser magnitude
5639 than both of the addends, it is sometimes an exact result. This
5640 is particularly common if the smaller addend was an integer,
5641 as in 143 + (-1). */
5642 if (((rv - b) != a) || ((rv - a) != b)) {
5643 return ERR_EXEC_SIG_LOSS;
5644 }
5645 }
5646 if (do_dx) {
5647 drv = da + db;
5648 }
5649 trv = TGMIN(tga, tgb); /* tgs-manip: Only rational if both terms were rational;
5650 likewise for integer */
5651 ms_push(ms, rv, drv, trv); *undo_count = 3;
5652 break;
5653
5654 case '*' :
5655 /* d/dx u v = v du + u dv */
5656 b = ms_pop(ms, &db, &tgb);
5657 a = ms_pop(ms, &da, &tga);
5658 if (do_dx) {
5659 drv = (ries_dif) ((b * da) + (a * db));
5660 }
5661 rv = a * b;
5662 trv = TGMIN(tga, tgb); /* tgs-manip: INT*INT->INT; INT*RAT -> RAT; RAT*RAT->RAT;
5663 (anything)*NONE->NONE */
5664 ms_push(ms, rv, drv, trv); *undo_count = 3;
5665 break;
5666
5667 case '/' :
5668 /* d/dx u/v = (v du - u dv) / v^2 */
5669 b = ms_pop(ms, &db, &tgb); *undo_count = 1;
5670 if (b == k_0) {
5671 return ERR_EXEC_DIV_ZERO;
5672 }
5673 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5674 if (do_dx) {
5675 drv = (ries_dif) (((b * da) - (a * db)) / (b * b));
5676 }
5677 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5678 return ERR_EXEC_ILLEGAL_DERIV;
5679 }
5680 rv = a / b;
5681 if ((tga >= TYPE_RAT) && (tgb >= TYPE_RAT)) {
5682 /* tgs-manip: We have INT/INT, RAT/INT, or RAT/RAT any of which may cause
5683 cancellation and result in an integer */
5684 trv = (rv == FLOOR(rv)) ? TYPE_INT : TYPE_RAT;
5685 } else {
5686 trv = TGMIN(tga, tgb);
5687 }
5688 /*printf("a %f tg %x b %f tg %x ans %f tg %x\n",a,tga,b,tgb,rv,trv);*/
5689 ms_push(ms, rv, drv, trv); *undo_count = 3;
5690 break;
5691
5692 case '^' : /* a to the power of b */
5693 /* d/dx u^v = v u^(v-1) du + ln(u) u^v dv */
5694 b = ms_pop(ms, &db, &tgb); *undo_count = 1;
5695 if (g_restrict_exponents) {
5696 if ((db != 0) /* b is a subexpression containing x */
5697 || (tgb < g_restrict_exponents)) {
5698 return ERR_EXEC_ILLEGAL_EXPONENT;
5699 }
5700 }
5701 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5702 if (a <= k_0) {
5703 /* This would give a complex answer except when b is an integer,
5704 but in that case there will always be another expression that
5705 gives the same value without needing to raise a negative number
5706 to a power. */
5707 return ERR_EXEC_POW_NEG_BASE;
5708 }
5709 if (FABS(b) < k_sig_loss) {
5710 /* loss-of-significance error, e.g. "2^0.001" */
5711 return ERR_EXEC_SIG_LOSS;
5712 }
5713 rv = POW(a, b);
5714 if (do_dx) {
5715 drv = (ries_dif) (rv * ( (b * da / a) + (LOG(a) * db) ));
5716 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5717 return ERR_EXEC_ILLEGAL_DERIV;
5718 }
5719 if ((da || db) && (drv == k_0)) {
5720 return ERR_EXEC_ZERO_DERIV;
5721 }
5722 }
5723 if (tgb == TYPE_INT) { /* tgs-manip */
5724 if (b >= 0) {
5725 trv = tga; /* INT^+INT->INT; RAT^+INT->RAT */
5726 } else {
5727 trv = TGMIN(tga, TYPE_RAT); /* INT^-INT->RAT; RAT^-INT->RAT */
5728 }
5729 } else if (tgb == TYPE_RAT) {
5730 /* tgs-manip: if b is 1/2 or 1/4 or 1/8, treat as sqrt */
5731 lb=FABS(b);
5732 if ((lb == 0.5) || (lb == 0.25) || (lb == 0.125)) {
5733 trv = TGMIN(tga, TYPE_CONS); /* We have sqrt(a) or 1/sqrt(a), etc. */
5734 } else {
5735 trv = TGMIN(tga, TYPE_ALG); /* Some other rational power/root */
5736 }
5737 } else if ((tgb == TYPE_CONS) || (tgb == TYPE_ALG)) {
5738 trv = TGMIN(tga, TYPE_ELEM);
5739 } else {
5740 /* Exponent isn't even algebraic! */
5741 trv = TGMIN(tga, tgb);
5742 }
5743 ms_push(ms, rv, drv, trv); *undo_count = 3;
5744 break;
5745
5746 case 'v' : /* the bth root of a, that is, a^(1/b) */
5747 b = ms_pop(ms, &db, &tgb); *undo_count = 1;
5748 if (g_restrict_exponents) {
5749 if ((db != 0) /* b is a subexpression containing x */
5750 || (tgb < g_restrict_exponents)) {
5751 return ERR_EXEC_ILLEGAL_EXPONENT;
5752 }
5753 }
5754 if (b == k_0) {
5755 return ERR_EXEC_OVERFLOW;
5756 }
5757 if (FABS(b) > (1.0 / k_sig_loss)) {
5758 /* loss-of-significance error, e.g. "100000,/2" */
5759 return ERR_EXEC_SIG_LOSS;
5760 }
5761 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5762 f1 = 0;
5763 if (b == k_3) {
5764 /* Cube root can handle any argument */
5765 if (a < k_0) {
5766 a = -a;
5767 f1 = 1;
5768 }
5769 } else if (a < k_0) {
5770 return ERR_EXEC_ROOT_NEG;
5771 }
5772 rv = POW(a, k_1 / b);
5773 if (do_dx) {
5774 drv = (ries_dif) (rv * ( (da / (a * b)) - (LOG(a) * db / (b*b)) ));
5775 if ((da || db) && (drv == k_0)) {
5776 return ERR_EXEC_ZERO_DERIV;
5777 }
5778 }
5779 if (f1) {
5780 rv = -rv;
5781 }
5782 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5783 return ERR_EXEC_ILLEGAL_DERIV;
5784 }
5785 if (tgb >= TYPE_RAT) { /* tgs-manip */
5786 lb=FABS(b);
5787 if ((lb==2.0) || (lb==4.0) || (lb==8.0)) {
5788 trv = TGMIN(tga, TYPE_CONS); /* sqrt(a) or 1/sqrt(a) */
5789 } else {
5790 trv = TGMIN(tga, TYPE_ALG); /* Some other rational power/root */
5791 /* NOTE: If b is an integer reciprocal then this would be like
5792 raising to an integer power, but the search will have found
5793 that first anyway */
5794 }
5795 } else if ((tgb == TYPE_CONS) || (tgb == TYPE_ALG)) {
5796 trv = TGMIN(tga, TYPE_ELEM);
5797 } else {
5798 /* Radix isn't even algebraic! */
5799 trv = TGMIN(tga, tgb);
5800 }
5801 ms_push(ms, rv, drv, trv); *undo_count = 3;
5802 break;
5803
5804 case 'L' : /* [<a><b>L] is the log base b of a, that is, ln(a)/ln(b) */
5805 b = ms_pop(ms, &db, &tgb); *undo_count = 1;
5806 if (g_restrict_exponents) {
5807 if ((db != 0) /* b is a subexpression containing x */
5808 || (tgb < g_restrict_exponents)) {
5809 return ERR_EXEC_ILLEGAL_EXPONENT;
5810 }
5811 }
5812 if ((b <= k_0) || (b == k_1)) {
5813 return ERR_EXEC_LOG_BAD_BASE;
5814 }
5815 if (FABS(1.0 - b) < k_sig_loss) {
5816 /* loss-of-significance error, e.g. "log_0.999(2)" or "log_1.001(2)" */
5817 return ERR_EXEC_SIG_LOSS;
5818 }
5819 a = ms_pop(ms, &da, &tga); *undo_count = 2;
5820 if (g_restrict_exponents) {
5821 if ((da != 0) /* a is a subexpression containing x */
5822 || (tga < g_restrict_exponents)) {
5823 return ERR_EXEC_ILLEGAL_EXPONENT;
5824 }
5825 }
5826 if (a <= k_0) {
5827 return ERR_EXEC_LOG_NEG;
5828 }
5829 if (FABS(a - 1.0) <= k_sig_loss) {
5830 /* loss-of-significance error, e.g. "log_2(1.00001)" */
5831 return ERR_EXEC_SIG_LOSS;
5832 }
5833 lb = LOG(b);
5834 rv = LOG(a) / lb;
5835 if (do_dx) {
5836 drv = (ries_dif) ((da / (a * lb)) - (rv * db / (b * lb)));
5837 if (!((drv < k_d_inf) && (drv > k_d_ninf))) {
5838 return ERR_EXEC_ILLEGAL_DERIV;
5839 }
5840 if ((da || db) && (drv == k_0)) {
5841 return ERR_EXEC_ZERO_DERIV;
5842 }
5843 }
5844 trv = TGMIN(tga, TGMIN(tgb, TYPE_ELEM)); /* tgs-manip */
5845 ms_push(ms, rv, drv, trv); *undo_count = 3;
5846 break;
5847
5848#if 0
5849 case 'A' : /* atan2 function (quadrant-correct arctangent) */
5850 b = ms_pop(ms, &db, 0);
5851 a = ms_pop(ms, &da, 0);
5852 rv = ARCTAN(a,b);
5853 if (do_dx) {
5854 /* %%% I need to verify this. It also needs to be transformed into
5855 a form that won't lose accuracy when computed (consider b near 0)
5856 probably need to use two forms: one for when fabs(a) > fabs(b),
5857 and one for the other case. */
5858 drv = (k_1 / (k_1 + (a*a / b*b))) * (b * da - a * db) / (b*b);
5859 }
5860 trv = TYPE_NONE; /* tgs-manip */
5861 ms_push(ms, rv, drv, trv); *undo_count = 3;
5862 break;
5863#endif
5864
5865 default:
5866 return ERR_EXEC_ILLEGAL_SYMBOL;
5867 }
5868
5869 if (debug_r) {
5870 if (do_dx && sym_attrs[op].seft == 'c') {
5871 printf("exec %8.5g", dbl(a));
5872 printf(" (%8.5g)%x", da, tga);
5873 printf(" '%c'", op);
5874 printf(" %8.5g", dbl(b));
5875 printf(" (%8.5g)%x", db, tgb);
5876 printf(" -> %10.6g", dbl(rv));
5877 printf(" d/dx=%10.6g", drv);
5878 } else {
5879 if (sym_attrs[op].seft != 'a') {
5880 printf("exec %14.10g", dbl(a));
5881 if (do_dx) {
5882 printf(" (%14.10g)", da);
5883 }
5884 printf("%x", tga);
5885 }
5886 printf(" '%c'", op);
5887 if (sym_attrs[op].seft == 'c') {
5888 printf(" %14.10g", dbl(b));
5889 if (do_dx) {
5890 printf(" (%14.10g)", db);
5891 }
5892 printf("%x", tgb);
5893 }
5894 printf(" -> %14.10g", dbl(rv));
5895 if (do_dx) {
5896 printf(" d/dx=%14.10g", drv);
5897 }
5898 printf(" tag %x", trv);
5899 }
5900 printf("\n");
5901 }
5902
5903 return 0;
5904} /* End of exec() */
5905
5906
5907/* F_ALLOC is the size used for fscratch, suitable for single-character infix
5908 format */
5909#define F_ALLOC (MAX_ELEN * 4)
5910
5911/* infix.1 pulls one full subexpression off the end of an expression,
5912 converts it to infix, and writes the result into the supplied "char * term".
5913 It is a recursive function, calling itself to infix-ize subexpressions.
5914 The result is still in one-character-per-symbol format.
5915 It also modifies the input expression by moving its terminating 0 backwards.
5916 It writes the term's final operator into t_op, which is to aid the caller
5917 in determining whether precedence will require the use of parentheses.
5918 infix.1 does not put parentheses around the term, however it
5919 does parenthesize subterms within the term. */
5920s16 infix_1(
5921 symbol * expr, /* The input */
5922 char * term, /* The output */
5923 symbol * t_op /* Output: final symbol from input ("top-level" symbol
5924 / of resulting infix) */
5925)
5926{
5927 s16 iptr, optr; /* input, output pointers */
5928 symbol op;
5929 /* st_a and st_b are allocated twice as large in case we're processing
5930 an RHS after try.solve */
5931 char st_a[F_ALLOC*2]; /* subterm A */
5932 symbol op_a; /* and its operator */
5933 char st_b[F_ALLOC*2]; /* subterm B */
5934 symbol op_b;
5935 s16 swap;
5936 char * term_a; /* for exchanging the two terms if we decide to do so */
5937 char * term_b; /* for exchanging the two terms if we decide to do so */
5938 symbol op_t; /* for swapping op_a and op_b */
5939 char * s; /* for copying subterms to output */
5940 s16 paren_a, paren_b; /* precedence flags for seft 'c' operators */
5941
5942 optr = 0;
5943 /* go to the end */
5944 iptr = 0;
5945 while(expr[iptr]) {
5946 iptr++;
5947 }
5948 /* check for underrun */
5949 if (iptr == 0) {
5950 return 1;
5951 }
5952 /* get the operator */
5953 --iptr; op = expr[iptr]; expr[iptr] = 0;
5954 *t_op = op;
5955 /* check its type */
5956 switch(sym_attrs[op].seft) {
5957 case 'a':
5958 /* oooh, this is easy */
5959 term[optr++] = (char) op;
5960 /* we terminate the input string here. */
5961 expr[iptr] = 0;
5962 break;
5963 case 'b':
5964 /* we've got the op, get the term */
5965 if(infix_1(expr, st_a, &op_a)) {
5966 return 1;
5967 }
5968 swap = 0;
5969 if (op == 's') {
5970 swap = 1;
5971 }
5972 paren_a = 1;
5973 if ((op == 'n') && (sym_attrs[op_a].seft != 'c')) {
5974 paren_a = 0;
5975 }
5976
5977 /* %%% what happens next should depend on op and op_a */
5978 if (swap == 0) {
5979 term[optr++] = (char) op;
5980 }
5981 if (paren_a) {
5982 term[optr++] = '(';
5983 }
5984 for(s = st_a; *s; s++) {
5985 term[optr++] = *s;
5986 }
5987 if (paren_a) {
5988 term[optr++] = ')';
5989 }
5990 if (swap) {
5991 term[optr++] = (char) op;
5992 }
5993 break;
5994 case 'c':
5995 /* get the terms */
5996 if(infix_1(expr, st_b, &op_b)) {
5997 return 1;
5998 }
5999 if(infix_1(expr, st_a, &op_a)) {
6000 return 1;
6001 }
6002
6003 /* default is to keep them in order */
6004 term_a = st_a; term_b = st_b; swap = 0;
6005
6006 /* optional swaps for the commutative operators
6007 if adding, try to put a constant at the end */
6008 if ((op == '+') && (sym_attrs[op_a].seft == 'a') && (op_a != 'x')) {
6009 swap = 1;
6010 }
6011 /* rules for multiplying */
6012 if (op == '*') {
6013 int a_has_x, b_has_x;
6014
6015 a_has_x = (strchr(term_a, 'x') != 0);
6016 b_has_x = (strchr(term_b, 'x') != 0);
6017 /* a bare seft-a symbol always precedes an expression
6018 %%% this swap should not be done if the baresymbol is 'x' and
6019 the expression has no 'x' */
6020 if ((! a_has_x) && (op_b == 'x')) {
6021 /* no swappy */
6022 } else if ((sym_attrs[op_a].seft != 'a') && (sym_attrs[op_b].seft == 'a')) {
6023 swap = 1;
6024 } else if ((op_a == 'x') && (! b_has_x)) {
6025 swap = 1;
6026 }
6027 /* with two bare symbols multiplied by each other, swap if the
6028 latter is an integer. Note: the integer test of op_b implicitly
6029 tests for the second term being seft-a. */
6030 if ((sym_attrs[op_a].seft == 'a') && (op_b >= '0') && (op_b <= '9')) {
6031 swap = 1;
6032 } else if ((op_a == 'x') &&
6033 ( (op_b == 'e') || (op_b == 'f') || (op_b == 'p')) ) {
6034 /* "x pi" -> "pi x" */
6035 swap = 1;
6036 }
6037 }
6038 /* Always swap for operators that are inherently swapped. */
6039 if (op == 'v') {
6040 swap = 1;
6041 } else if (op == 'L') {
6042 swap = 1;
6043 }
6044 /* Check for phantom symbols */
6045 if (op == PS_REVSUB) {
6046 swap = 1;
6047 op = '-';
6048 *t_op = '-';
6049 } else if (op == PS_REVDIV) {
6050 swap = 1;
6051 op = '/';
6052 *t_op = '/';
6053 } else if (op == PS_REVPOW) {
6054 swap = 1;
6055 op = '^';
6056 *t_op = '^';
6057 }
6058
6059 /* okay, do the swap */
6060 if (swap) {
6061 term_a = st_b; term_b = st_a;
6062 op_t = op_a; op_a = op_b; op_b = op_t;
6063 }
6064
6065 /* determine precedence */
6066 paren_a = paren_b = 0; /* default don't use parens */
6067
6068 if (op == 'L') {
6069 /* Latter part is always in parens; first part (base) is
6070 in parens only if it's an expression */
6071 paren_b = 1;
6072 if (sym_attrs[op_a].seft != 'a') {
6073 paren_a = 1;
6074 }
6075 }
6076 if (sym_attrs[op_a].seft == 'c') {
6077 /* We have (s1 op_a s2) op s3 */
6078 paren_a = 1; /* default use parens */
6079 if (strchr("+*/^v", op_a) && strchr("+-", op)) {
6080 /* anything followed by + or - doesn't need parens */
6081 paren_a = 0;
6082 } else if (strchr("*^v", op_a) && strchr("*/", op)) {
6083 /* * ^ or v followed by * or / doesn't need parens */
6084 paren_a = 0;
6085 }
6086 }
6087 if (sym_attrs[op_b].seft == 'c') {
6088 /* We have s1 op (s2 op_b s3) */
6089 paren_b = 1; /* default use parens */
6090 if ((op == '+') && strchr("+-*/^v", op_b)) {
6091 /* + followed by anything doesn't need parens */
6092 paren_b = 0;
6093 } else if ((op == '-') && strchr("*/^v", op_b)) {
6094 /* - followed by mult or higher operators doesn't need parens */
6095 paren_b = 0;
6096 } else if ((op == '*') && strchr("*/^v", op_b)) {
6097 /* * followed by mult or higher operators doesn't need parens */
6098 paren_b = 0;
6099 } else if ((op == '/') && strchr("^v", op_b)) {
6100 /* / followed by ^ or v doesn't need parens */
6101 paren_b = 0;
6102 }
6103 }
6104
6105 /* We're all set to generate output. */
6106
6107 /* Emit leading operator for two-argument custom functions and 'L' */
6108 if (op == 'L') {
6109 /* This operator goes in front of both arguments */
6110 term[optr++] = (char) op;
6111 }
6112
6113 /* Emit first argument */
6114 if (paren_a) {
6115 term[optr++] = '(';
6116 }
6117 for(s = term_a; *s; s++) {
6118 term[optr++] = *s;
6119 }
6120 if (paren_a) {
6121 term[optr++] = ')';
6122 }
6123
6124 /* Emit infix operator */
6125 if (op == '*') {
6126 if (g_explicit_multiply) {
6127 term[optr++] = (char) op; /* emit an actual "*" */
6128 } else if ((op_a <= '9') && paren_b) {
6129 /* digit times anything starting with parentheses */
6130 /* Emit no symbol at all */
6131 } else if ((op_a <= '9') && (term_b[0] <= '9')) {
6132 /* digit times anything starting with a bare digit */
6133 term[optr++] = (char) op; /* emit an actual "*" */
6134 } else if (op_b == 'n') {
6135 /* A times negative B, require explicit '*' */
6136 term[optr++] = (char) op;
6137 } else if ((sym_attrs[op_a].seft != 'a') || (sym_attrs[op_b].seft != 'a')
6138 || (term_b[0] > '9')) {
6139 /* printf("op_a '%c' op_b '%c' mult '.'\n", op_a, op_b); */
6140 term[optr++] = '.'; /* This becomes a blank space " " */
6141 } else {
6142 term[optr++] = (char) op;
6143 }
6144 } else if (op == 'L') {
6145 /* We already emitted it */
6146 } else {
6147 term[optr++] = (char) op;
6148 }
6149
6150 /* Emit second argument */
6151 if (paren_b) {
6152 term[optr++] = '(';
6153 }
6154 for(s = term_b; *s; s++) {
6155 term[optr++] = *s;
6156 }
6157 if (paren_b) {
6158 term[optr++] = ')';
6159 }
6160 break;
6161 }
6162
6163 /* terminate input and output strings */
6164 term[optr] = 0;
6165
6166 return 0;
6167} /* End of infix.1 */
6168
6169/* cv.phantoms takes a symstr and converts any phantom symbols to
6170their ASCII equivlents. symstrs with phantom symbols are fairly
6171short-lived, because they are created only by infix.preproc and then
6172immediately converted by infix.1 */
6173void cv_phantoms(symbol * s)
6174{
6175 if (s) {
6176 while(*s) {
6177 if (*s == PS_REVSUB) {
6178 *s = '_';
6179 } else if (*s == PS_REVDIV) {
6180 *s = '\\';
6181 } else if (*s == PS_REVPOW) {
6182 *s = '`';
6183 }
6184 s++;
6185 }
6186 }
6187}
6188
6189/* infix.preproc copies "expr" to "out", and performs manipulations on
6190expressions that make the infix conversion easier.
6191 For example, the "squared" operator [s] gets turned into "^2" [2^].
6192That gives the infix conversion less special cases to check for when
6193it figures out where to put the parentheses. We can also do some
6194simplification here, for example [xn2+] which is "-x+2" in infix,
6195becomes [x2_] "2-x". */
6196void infix_preproc(symbol * expr, symbol * out)
6197{
6198 symbol * s;
6199 symbol * o;
6200 s = expr;
6201 o = out;
6202
6203 if (debug_p) { printf("infix.preproc input [%s]\n", expr); }
6204
6205 while(*s) {
6206 if (0) {
6207
6208 } else if ((*s == '-') && (*(s+1) == 'n')) {
6209 /* [-n] is seen when --canon-reduction is used. Here we convert
6210 [-n] "-(a-b)" into [_] "b-a", where '_' represents the reversed
6211 subtract phantom op. This makes e.g. "1/-(x-pi)" into "pi-x". */
6212 if (debug_p) { printf(" [-n]->[_]\n"); }
6213 *o++ = PS_REVSUB;
6214 s ++;
6215
6216 } else if ((*s == '/') && (*(s+1) == 'r')) {
6217 /* [/r] is also seen when --canon-reduction is enabled, e.g. [27/r]
6218 in the output of "ries 2.4284920346331 --canon-reduction nr25".
6219 Here we convert [/r] "1/(a/b)" into [\] "b/a", where '\' is
6220 reversed division. */
6221 if (debug_p) { printf(" [/r]->[\\]\n"); }
6222 *o++ = PS_REVDIV;
6223 s ++;
6224
6225 } else if (*s == ' ') {
6226 /* ' ' is a no-op */
6227 } else if ((*s == 'n') && (sym_attrs[*(s+1)].seft == 'a') && (*(s+2) == '+')) {
6228 /* converting [n2+] into [2_]. Test case: 1.3204 gives
6229 "-(x)+2 = e/4" without this conversion and "2-x = e/4" with. */
6230 if (debug_p) { printf(" [nA+]->[A_]\n"); }
6231 *o++ = *(s+1);
6232 *o++ = PS_REVSUB;
6233 s += 2;
6234 } else if (*s == 's') {
6235 /* [s] -> [2^] */
6236 if (debug_p) { printf(" [s]->[2^]\n"); }
6237 *o++ = '2';
6238 *o++ = '^';
6239 } else if (*s == 'r') {
6240 /* [r] -> [1\] */
6241 if (debug_p) { printf(" [r]->[1\\]\n"); }
6242 *o++ = '1';
6243 *o++ = PS_REVDIV;
6244 } else if (*s == 'E') {
6245 /* [E] -> [e`] where ` is reverse power */
6246 if (debug_p) { printf(" [E]->[e`]\n"); }
6247 *o++ = 'e';
6248 *o++ = PS_REVPOW;
6249 } else {
6250 *o++ = *s;
6251 }
6252 s++;
6253 }
6254 *o++ = 0;
6255 if (debug_p) {
6256 symbol prtmp[EXPR_ALLOC];
6257 symstrncpy0(prtmp, out, EXPR_ALLOC);
6258 cv_phantoms(prtmp);
6259 printf(" result: [%s]\n", prtmp);
6260 }
6261}
6262
6263/* symstrsym is like strchr for symbol strings. */
6264symbol * symstrsym(symbol * exp1, symbol sym)
6265{
6266 while((*exp1) && (*exp1 != sym)) {
6267 exp1++;
6268 }
6269 if (*exp1) {
6270 return exp1;
6271 }
6272 return 0;
6273}
6274
6275/* symstrlen is just like strlen, for symbol strings. */
6276unsigned int symstrlen(symbol * s)
6277{
6278 unsigned int l;
6279 if (s == 0) {
6280 return 0;
6281 }
6282 for(l=0; s[l]; l++) { }
6283 return l;
6284}
6285
6286/* symstrtrail detects a literal trailing pattern: it examines "big"
6287to see if it ends with the same characters as "little". In most odd
6288cases (e.g. if either string is null or 'little' is longer than 'big')
6289it returns 0. */
6290int symstrtrail(symbol * big, symbol * little)
6291{
6292 unsigned int i, l1, l2;
6293 symbol * s;
6294 l1 = symstrlen(big);
6295 l2 = symstrlen(little);
6296 if ((l1 == 0) || (l2 == 0)) {
6297 return 0;
6298 }
6299 if (l1 < l2) {
6300 return 0;
6301 }
6302 s = big + (((int)l1) - ((int)l2));
6303 for(i=0; i<l2; i++) {
6304 if (s[i] != little[i]) {
6305 return 0;
6306 }
6307 }
6308 return 1;
6309}
6310
6311int bothtrail(symbol * a, symbol * b, symbol *tr)
6312{
6313 int rv;
6314 rv = symstrtrail(a, tr) && symstrtrail(b, tr);
6315 return rv;
6316}
6317
6318/* symstrclip removes len symbols from the end of a symbol string (but does
6319nothing if the symbol string doesn't have that many symbols to start with) */
6320void symstrclip(symbol * s, unsigned int len)
6321{
6322 unsigned int l;
6323 l = symstrlen(s);
6324 if (l >= len) {
6325 l -= len;
6326 s[l] = 0;
6327 }
6328}
6329
6330/* symstrcmp is like strcmp for symbol strings. */
6331int symstrcmp(symbol * a, symbol * b)
6332{
6333 while((*a) && (*b) && (*a == *b)) {
6334 a++;
6335 b++;
6336 }
6337 if ((*a == 0) && (*b == 0)) {
6338 return 0;
6339 }
6340 if (*a == 0) {
6341 /* a ended, so b is lexicographically later */
6342 return -1;
6343 }
6344 if (*b == 0) {
6345 /* b ended, so a is later */
6346 return 1;
6347 }
6348 if ((*a) > (*b)) {
6349 return 1;
6350 }
6351 return -1;
6352}
6353
6354/* symstrneq compares the first n symbols in two strings; it returns 1 only
6355 of that many symbols exist in both strings and all are equal. */
6356int symstrneq(symbol * a, symbol * b, unsigned int n)
6357{
6358 unsigned int i;
6359 i = 0;
6360 while((*a) && (*b) && (*a == *b) && (i<n)) {
6361 a++;
6362 b++;
6363 i++;
6364 }
6365 if (i== n) {
6366 return 1;
6367 }
6368 return 0;
6369}
6370
6371/* sym.strsymstr is like strstr for symbol strings. */
6372symbol * symstrsymstr(symbol * haystack, symbol * needle)
6373{
6374 symbol * hs = haystack;
6375 symbol c1;
6376 unsigned int l, n;
6377
6378 n = 0;
6379 if ((hs == 0) || (needle == 0)) {
6380 return 0;
6381 }
6382 l = symstrlen(needle);
6383 /* The null string occurs at the beginning of every string */
6384 if (l == 0) {
6385 /* printf("symstrsymstr: r1\n"); */
6386 return haystack;
6387 }
6388 c1 = *needle;
6389 /* General case */
6390 while(hs && (*hs)) {
6391 hs = symstrsym(hs, c1);
6392 n++;
6393 if (hs == 0) {
6394 /* printf("symstrsymstr: r0a\n"); */
6395 return 0;
6396 }
6397 if (symstrneq(hs, needle, l)) {
6398 /* printf("symstrsymstr: r2\n"); */
6399 return hs;
6400 }
6401 hs++;
6402 }
6403 /* printf("symstrsymstr: r0b '%s' n=%d '%s'\n",
6404 (char*)needle,n,(char*)haystack); */
6405 return 0;
6406}
6407
6408/* symstrncpy0 is kind of like strncpy for symbol strings, except
6409 that it ensures the last symbol copied will be 0. */
6410int symstrncpy0(symbol *to, symbol *from, int len)
6411{
6412 int l = 0;
6413 if ((to == 0) || (len <=0)) {
6414 return 0;
6415 }
6416 if (from == 0) {
6417 *to = 0;
6418 return 0;
6419 }
6420 while ((from[l]) && (l+1 < len)) {
6421 to[l] = from[l];
6422 l++;
6423 }
6424 to[l] = 0; l++;
6425 return(l);
6426}
6427
6428/* sym.strncat is kind of like strncat for symbol strings */
6429void symstrncat(symbol *to, symbol *from, long len)
6430{
6431 int l = 0;
6432
6433 if ((to == 0) || (len <=0)) {
6434 return;
6435 }
6436 /* Now get length of existing dest string */
6437 while(to[l]) {
6438 l++;
6439 }
6440 if (from == 0) {
6441 return;
6442 }
6443 while ((*from) && (l+1 < len)) {
6444 to[l++] = *from++;
6445 }
6446 to[l++] = 0;
6447
6448 return;
6449}
6450
6451void str_remap(char *s, char from, char to)
6452{
6453 while(s && (*s)) {
6454 if (*s == from) {
6455 *s = to;
6456 }
6457 s++;
6458 }
6459}
6460
6461/* infix_expand expands the output of infix.1 into something more
6462 human-readable. It returns the length of the output. */
6463s16 infix_expand(char * input, char * output)
6464{
6465 s16 i, l;
6466 size_t j, l2;
6467 symbol c;
6468
6469 l = (s16) strlen(input);
6470 j = 0;
6471 for(i=0; i<l; i++) {
6472 c = (symbol) input[i];
6473 /* printf("sym '%c', name '%s'\n", c, symbol_names[c]); */
6474 l2 = strlen(sym_attrs[c].sa_name);
6475 ries_strncpy(output+j, (char *) (sym_attrs[c].sa_name), (int)l2);
6476 j = j + l2;
6477 }
6478 output[j] = 0;
6479 return((s16) j);
6480}
6481
6482/* postfix converts an expression (in its native postfix format, i.e. a
6483/ null-terminated array of symbol) to a character string in the old RIES
6484/ "compact postfix format". This is currently just one character per symbol,
6485/ so it does little more than strcpy would. However, if the symbolspace is
6486/ expanded to more than 256, or when custom-definable symbols are possible,
6487/ the simple one byte to one byte mapping will no longer apply. */
6488s16 postfix(symbol * expr, char * out)
6489{
6490 symbol * s;
6491 char * o;
6492
6493 for(s = expr, o = out; (*o++ = (char)(*s++));) {
6494 }
6495 return 0;
6496}
6497
6498/* Convert a compact postfix expression into a more human-readable form */
6499s16 postfix_formatter(symbol * expr, char * out, s16 maxlen)
6500{
6501 char cv_scratch[EXPR_ALLOC];
6502 s16 i, len;
6503 symbol c;
6504
6505 len = 0;
6506 maxlen--;
6507 if (postfix(expr, cv_scratch)) {
6508 /* error */
6509 return 0;
6510 } else {
6511 const char * s;
6512
6513 for(i=0; cv_scratch[i] && (len < maxlen); i++) {
6514 c = (symbol) cv_scratch[i];
6515 if(sym_attrs[c].name_forth) {
6516 s = sym_attrs[c].name_forth;
6517 while(*s && (len < maxlen)) {
6518 out[len++] = *s++;
6519 }
6520 } else if (len < maxlen) {
6521 out[len++] = (char) c;
6522 }
6523 if (len < maxlen) {
6524 out[len++] = ' ';
6525 }
6526 }
6527 }
6528
6529 /* Ensure the output ends in a null, and remove any final spaces */
6530 out[len] = 0;
6531 while ((len > 0) && (out[len-1] == ' ')) {
6532 len--;
6533 out[len] = 0;
6534 }
6535
6536 return len;
6537}
6538
6539/* complexity simply adds up the complexity scores (weights) in an
6540 expression. */
6541s16 complexity(symbol * expr)
6542{
6543 symbol sym;
6544 s16 comp;
6545
6546 comp = 0;
6547 while((sym = *expr++)) {
6548 comp = (s16) (comp + sym_attrs[sym].sa_wgt);
6549 }
6550 return comp;
6551}
6552
6553/* endstack goes through an expression and determines how many things
6554 it leaves on the stack when it is done. It also returns pointers to
6555 the last symbol in the expression, and the last symbol that left the stack
6556 with one item on it. These are all useful in expr_break(). */
6557int endstack(symbol * expr, int *ending_sp, symbol * * last_sp_1,
6558 symbol * * last_sym)
6559{
6560 symbol sym, sf;
6561 int sp;
6562 symbol * ex;
6563 symbol * lsp1;
6564
6565 ex = expr;
6566 sp = 0; lsp1 = 0;
6567 while((sym = *ex)) {
6568 /* Look at the symbol's seft */
6569 sf = sym_attrs[sym].seft;
6570 if (sf == 'a') {
6571 /* Push a constant onto the stack */
6572 sp++;
6573 } else if (sf == 'b') {
6574 /* Single-argument function */
6575 } else if (sf == 'c') {
6576 /* Two-argument function */
6577 sp--;
6578 }
6579
6580 /* Check for trouble */
6581 if (sp <= 0) {
6582 /* Nothing on the stack -- this means we underflowed */
6583 printf("endstack underflow\n");
6584 return ERR_EVAL_STACK_UNDERFLOW;
6585 }
6586
6587 /* Keep track of the last place where the stack was 1. */
6588 if ((sp == 1) && (*(ex+1))) {
6589 lsp1 = ex;
6590 }
6591
6592 ex++;
6593 }
6594 /* Go back to the final symbol */
6595 ex--;
6596 if (ex < expr) {
6597 printf("endstack null\n");
6598 return ERR_ES_NULL_EXPRESSION;
6599 }
6600
6601 if (ending_sp) {
6602 *ending_sp = sp;
6603 }
6604 if (last_sp_1) {
6605 *last_sp_1 = lsp1;
6606 }
6607 if (last_sym) {
6608 *last_sym = ex;
6609 }
6610
6611 return 0; /* No error */
6612} /* End of endstack */
6613
6614/* Break an expression up into its root operator and the argument(s) if any. */
6615int expr_break(symbol * expr, symbol * op, symbol * seft,
6616 symbol * * arg1, int * a1_len, symbol * * arg2, int * a2_len)
6617{
6618 int ending_sp, err;
6619 symbol * last_sp_1;
6620 symbol * last_sym;
6621 symbol sf;
6622
6623 /* Set some default return values */
6624 if (arg1) { *arg1 = 0; } if (arg2) { *arg2 = 0; }
6625 if (a1_len) { *a1_len = 0; } if (a2_len) { *a2_len = 0; }
6626
6627 err = endstack(expr, &ending_sp, &last_sp_1, &last_sym);
6628 if (err) {
6629 printf("endstack err %d\n", err);
6630 return err;
6631 }
6632 if (ending_sp > 1) {
6633 printf("expr_break incomplete (sp=%d)\n", ending_sp);
6634 return ERR_EC_INCOMPLETE_EXPR;
6635 }
6636 sf = sym_attrs[*last_sym].seft;
6637 if (op) { *op = *last_sym; }
6638 if (seft) { *seft = sf; }
6639 if (sf == 'a') {
6640 /* It's a constant, and should be just one symbol long. There
6641 are no arguments. */
6642 } else if (sf == 'b') {
6643 /* Operator is a single-argument function, and the entire rest of the
6644 expression is its argument */
6645 if (arg1) { *arg1 = expr; }
6646 if (a1_len) { *a1_len = ((int) ((last_sym - expr))); }
6647 } else if (sf == 'c') {
6648 /* Operator is a two-argument function, and the two arguments are
6649 divided at the point marked by last_sp_1
6650 23+r 2s3r+
6651 ^ ^^ ^ ^ ^ */
6652 if (arg1) { *arg1 = expr; }
6653 if (a1_len) { *a1_len = ((int) (last_sp_1 - expr) + 1); }
6654 if (arg2) { *arg2 = last_sp_1+1; }
6655 if (a2_len) { *a2_len = ((int) (last_sym - last_sp_1) - 1); }
6656 }
6657 return 0;
6658}
6659
6660/*
6661 expr_print_infix does everything needed to format an expression
6662(which must be complete) into an infix string and print it.
6663 To right-justify the output, pass a positive field width in the justify
6664parameter. */
6665void expr_print_infix(symbol * expr, int justify)
6666{
6667 symbol escratch[EXPR_ALLOC];
6668 char fscratch[F_ALLOC];
6669 char gscratch[MAX_ELEN * MAX_SYM_NAME_LEN];
6670 symbol ss;
6671
6672 infix_preproc(expr, escratch);
6673 infix_1(escratch, fscratch, &ss);
6674 infix_expand(fscratch, gscratch);
6675 if (justify > 0) {
6676 int j;
6677 for(j=((int)strlen(gscratch)); j<justify; j++) {
6678 printf(" ");
6679 }
6680 }
6681 printf("%s", gscratch);
6682}
6683
6684void eqn_print_infix(symbol * lhs, symbol * rhs)
6685{
6686 expr_print_infix(lhs, 0);
6687 printf(" = ");
6688 expr_print_infix(rhs, 0);
6689}
6690
6691/* eval evaluates an expression; useful for retrieving the values of both
6692 sides after a match, or for iterating Newton's method. It returns
6693 an error if it doesn't evaluate for some reason.
6694
6695 expr - The expression to evaluate
6696 val - Pointer to place to store the value (may be 0)
6697 dx - Pointer to place to put the derivative (may be 0)
6698 tag - Pointer to place to put the tags (may be 0)
6699 sptr - Pointer to place to put the final stack pointer value
6700 show_work - Nonzero to display work (for -Ds option)
6701
6702Return value is an error code like ERR_EVAL_TOO_LONG
6703 */
6704s16 eval(symbol * expr, ries_val * val, ries_dif * dx, ries_tgs * tags,
6705 s16 * sptr, s16 show_work)
6706{
6707 s16 contains_x;
6708 metastack ms;
6709 symbol * s;
6710 symbol dbg_scratch[EXPR_ALLOC];
6711 s16 err, i;
6712 s16 undo_count;
6713
6714 contains_x = (symstrsym(expr, 'x') != 0);
6715
6716 /* default return values */
6717 if (val) { *val = k_0; }
6718 if (dx) { *dx = (ries_dif) k_0; }
6719 if (tags) { *tags = 0; }
6720
6721 ms_init(&ms);
6722 for(s = expr, i=0; s[i]; i++) {
6723 if (i >= MAX_ELEN) {
6724 return ERR_EVAL_TOO_LONG;
6725 } else {
6726 /* Determine if the metastack will overflow */
6727 int sp1 = 0; int sp2 = 0; int ms1 = 0;
6728 switch (sym_attrs[s[i]].seft) {
6729 /* number of: pops pushes actions */
6730 case '0': ; break;
6731 case 'a': ; sp2 = 1; ms1 = 1; break;
6732 case 'b': ; sp1 = 1; ms1 = 2; break;
6733 case 'c': ; sp1 = 2; ms1 = 3; break;
6734 default: ; return ERR_EVAL_UNKNOWN_SEFT;
6735 }
6736 if (ms.sp < sp1) {
6737 return ERR_EVAL_STACK_UNDERFLOW;
6738 }
6739 if (ms.sp + sp2 > MS_STK_MAX) {
6740 return ERR_EVAL_STACK_OVERFLOW;
6741 }
6742 if (ms.msp + ms1 > MS_UNDO_MAX) {
6743 return ERR_EVAL_METASTACK_OVERFLOW;
6744 }
6745
6746 err = exec(&ms, s[i], &undo_count, contains_x);
6747 if (err) {
6748 return err;
6749 }
6750 if (debug_N || show_work) {
6751 symbol escratch[EXPR_ALLOC];
6752 char fscratch[F_ALLOC];
6753 char gscratch[MAX_ELEN * MAX_SYM_NAME_LEN];
6754 symbol ss;
6755 ries_val v;
6756 ries_dif dv;
6757 ries_tgs tg;
6758 s16 j;
6759
6760 dbg_scratch[i] = s[i];
6761 dbg_scratch[i+1] = 0;
6762 infix_preproc(dbg_scratch, escratch);
6763 err = infix_1(escratch, fscratch, &ss);
6764 infix_expand(fscratch, gscratch);
6765 v = ms_peek(&ms, &dv, &tg, 0);
6766 if (debug_N) { printf("eval "); }
6767 for(j=(s16)strlen(gscratch); j<27; j++) {
6768 printf(" ");
6769 }
6770 printf("%s = ", gscratch);
6771 spfg(k_nominal_digits, v); /* printf(fmt_g_nom_fixed, v); */
6772 if (dv != k_0) {
6773 printf(" (d/dx = ");
6774 printf(fmt_g_diff, dv);
6775 printf(")");
6776 }
6777 printf(" %s\n", tagname(tg));
6778 }
6779 }
6780 }
6781
6782 { /* Store any requested results in the pointers passed to us */
6783 ries_val v;
6784 v = ms_peek(&ms, dx, tags, sptr);
6785 if (val) { *val = v; }
6786 }
6787
6788 return 0;
6789} /* End of eval */
6790
6791/* try.solve does most of the algebraic manipulation to convert an equation
6792into the form "x = ...". If there are multiple x's in the input, it
6793doesn't notice and simply pushes everything to the RHS.
6794 There are a few special things to note:
6795 * The handling of [<l>s]=[<r>] deals with a branch case: when
6796transforming this to [<l>]=[<r>q], the signs might disagree. An
6797example is shown by "ries 0.8183431428522" which finds [x3-s]=[pf+].
6798After removing 's' and adding 'q' it calls eval() on the resulting
6799expressions and if their signs disagree, it negates the RHS to give
6800[<l>]=[<r>qn].
6801 * The sqrt sign check and others like it are subject to inaccuracies
6802if eval() is using g_target instead of the root of the current
6803equation as found by newton(). We could improve this by changing
6804exec.x temporarily, and restoring it afterwards the way newton() does;
6805or by making the exec.x an explicit parameter of eval().
6806 * Most seft-c operators can be solved by appending arg2 to the RHS,
6807by manipulating the lhs and rhs strings in-place. [L] is an exception:
6808[<a><b>L]=[<c>] must be converted into [<a>]=[<b><c>^], and it uses an
6809extra temp buffer "rtmp[]".
6810 */
6811#define TS_ALLOC_L EXPR_ALLOC
6812#define TS_ALLOC_R (EXPR_ALLOC*4)
6813void try_solve(symbol * l, symbol * r,
6814 symbol * l_out, int l_len, symbol * r_out, int r_len)
6815{
6816 symbol op, seft;
6817 symbol * arg1; int a1_len;
6818 symbol * arg2; int a2_len;
6819
6820 symbol lhs[TS_ALLOC_L];
6821 symbol part1[TS_ALLOC_L];
6822 symbol part2[TS_ALLOC_L];
6823 symbol rhs[TS_ALLOC_R];
6824 symbol tmpc[TS_ALLOC_R];
6825
6826 unsigned int gg, l1;
6827
6828 symstrncpy0(lhs, l, TS_ALLOC_L);
6829 symstrncpy0(rhs, r, TS_ALLOC_R);
6830 /* printf("try.solve [%s]:[%s]\n", lhs, rhs); */
6831
6832 gg = 1;
6833 while(gg) {
6834 op = 0;
6835 expr_break(lhs, &op, &seft, &arg1, &a1_len, &arg2, &a2_len);
6836
6837 symstrncpy0(part1, arg1, a1_len+1);
6838 symstrncpy0(part2, arg2, a2_len+1);
6839 /* printf("try.solve: [%s] [%s] [%c] %c\n", part1, part2, op, seft); */
6840
6841 if (0) {
6842 /* -------------------- Seft c symbols -------------------- */
6843 } else if (op == '+') {
6844 if (debug_S) {
6845 printf("transforming: ");
6846 eqn_print_infix(lhs, rhs);
6847 printf("\n by subtracting '");
6848 expr_print_infix(part2, 0);
6849 printf("' from both sides\n");
6850 }
6851 /* printf("construct [%s]:['%s'%s'-']\n", part1, rhs, part2); */
6852 symstrncat(rhs, part2, TS_ALLOC_R);
6853 symstrncat(rhs, ((symbol *) "-"), TS_ALLOC_R);
6854 symstrncpy0(lhs, part1, TS_ALLOC_L);
6855 /* printf("now [%s]:[%s]\n", lhs, rhs); */
6856 } else if (op == '-') {
6857 if (debug_S) {
6858 printf("transforming: ");
6859 eqn_print_infix(lhs, rhs);
6860 printf("\n by adding '");
6861 expr_print_infix(part2, 0);
6862 printf("' to both sides\n");
6863 }
6864 symstrncat(rhs, part2, TS_ALLOC_R);
6865 symstrncat(rhs, ((symbol *) "+"), TS_ALLOC_R);
6866 symstrncpy0(lhs, part1, TS_ALLOC_L);
6867 } else if (op == '*') {
6868 if (debug_S) {
6869 printf("transforming: ");
6870 eqn_print_infix(lhs, rhs);
6871 printf("\n by dividing both sides by '");
6872 expr_print_infix(part2, 0);
6873 printf("'\n");
6874 }
6875 symstrncat(rhs, part2, TS_ALLOC_R);
6876 symstrncat(rhs, ((symbol *) "/"), TS_ALLOC_R);
6877 symstrncpy0(lhs, part1, TS_ALLOC_L);
6878 } else if (op == '/') {
6879 if (debug_S) {
6880 printf("transforming: ");
6881 eqn_print_infix(lhs, rhs);
6882 printf("\n by multiplying both sides by '");
6883 expr_print_infix(part2, 0);
6884 printf("'\n");
6885 }
6886 symstrncat(rhs, part2, TS_ALLOC_R);
6887 symstrncat(rhs, ((symbol *) "*"), TS_ALLOC_R);
6888 symstrncpy0(lhs, part1, TS_ALLOC_L);
6889 } else if (op == '^') {
6890 if (debug_S) {
6891 printf("transforming: ");
6892 eqn_print_infix(lhs, rhs);
6893 printf("\n by taking the '");
6894 expr_print_infix(part2, 0);
6895 printf("' root of both sides\n");
6896 }
6897 symstrncat(rhs, part2, TS_ALLOC_R);
6898 symstrncat(rhs, ((symbol *) "v"), TS_ALLOC_R);
6899 symstrncpy0(lhs, part1, TS_ALLOC_L);
6900 } else if (op == 'L') {
6901 /* [<p1><p2>L] = [<r>] log to base <part2> of <part1> = <rhs>
6902 [<p1>] = [<p2><r>^] <part1> = <part2> ^ <rhs> */
6903 symbol rtmp[TS_ALLOC_R];
6904
6905 if (debug_S) {
6906 printf("transforming: ");
6907 eqn_print_infix(lhs, rhs);
6908 printf("\n by raising '");
6909 expr_print_infix(part2, 0);
6910 printf("' to the power of both sides\n");
6911 }
6912 symstrncpy0(rtmp, part2, TS_ALLOC_R);
6913 symstrncat(rtmp, rhs, TS_ALLOC_R);
6914 symstrncat(rtmp, ((symbol *) "^"), TS_ALLOC_R);
6915 symstrncpy0(rhs, rtmp, TS_ALLOC_R);
6916 symstrncpy0(lhs, part1, TS_ALLOC_L);
6917 } else if (op == 'v') {
6918 if (debug_S) {
6919 printf("transforming: ");
6920 eqn_print_infix(lhs, rhs);
6921 printf("\n by raising both sides to the '");
6922 expr_print_infix(part2, 0);
6923 printf("' power\n");
6924 }
6925 symstrncat(rhs, part2, TS_ALLOC_R);
6926 symstrncat(rhs, ((symbol *) "^"), TS_ALLOC_R);
6927 symstrncpy0(lhs, part1, TS_ALLOC_L);
6928
6929 /* -------------------- Seft b symbols -------------------- */
6930
6931 } else if (op == 'E') {
6932 if (debug_S) {
6933 printf("transforming: ");
6934 eqn_print_infix(lhs, rhs);
6935 printf("\n by taking the natural logarithm of both sides\n");
6936 }
6937 /* printf("construct [%s]:['%s'l']\n", part1, rhs); */
6938 symstrncat(rhs, ((symbol *) "l"), TS_ALLOC_R);
6939 symstrncpy0(lhs, part1, TS_ALLOC_L);
6940 /* printf("now [%s]:[%s]\n", lhs, rhs); */
6941 } else if (op == 'l') {
6942 if (debug_S) {
6943 printf("transforming: ");
6944 eqn_print_infix(lhs, rhs);
6945 printf("\n by raising e to the power of both sides\n");
6946 }
6947 symstrncat(rhs, ((symbol *) "E"), TS_ALLOC_R);
6948 symstrncpy0(lhs, part1, TS_ALLOC_L);
6949 } else if (op == 'n') {
6950 if (debug_S) {
6951 printf("transforming: ");
6952 eqn_print_infix(lhs, rhs);
6953 printf("\n by negating both sides\n");
6954 }
6955 symstrncat(rhs, ((symbol *) "n"), TS_ALLOC_R);
6956 symstrncpy0(lhs, part1, TS_ALLOC_L);
6957 } else if (op == 'q') {
6958 if (debug_S) {
6959 printf("transforming: ");
6960 eqn_print_infix(lhs, rhs);
6961 printf("\n by squaring both sides\n");
6962 }
6963 symstrncat(rhs, ((symbol *) "s"), TS_ALLOC_R);
6964 symstrncpy0(lhs, part1, TS_ALLOC_L);
6965 } else if (op == 'r') {
6966 if (debug_S) {
6967 printf("transforming: ");
6968 eqn_print_infix(lhs, rhs);
6969 printf("\n by taking the reciprocal of both sides\n");
6970 }
6971 symstrncat(rhs, ((symbol *) "r"), TS_ALLOC_R);
6972 symstrncpy0(lhs, part1, TS_ALLOC_L);
6973 } else if (op == 's') {
6974 ries_val lsqrt, rsqrt;
6975 if (debug_S) {
6976 printf("transforming: ");
6977 eqn_print_infix(lhs, rhs);
6978 printf("\n by taking the square root of both sides\n");
6979 }
6980 symstrncat(rhs, ((symbol *) "q"), TS_ALLOC_R);
6981 symstrncpy0(lhs, part1, TS_ALLOC_L);
6982 /* Since we took a square root, we now have to ensure that both
6983 sides of the equation agree as to which square root (positive
6984 or negative) generates the match. For example, one answer
6985 given for 0.8183431428522 is "(x-3)^2 = phi+pi"; when solving
6986 we'd get "x = sqrt(phi+pi)+3" unless we do these tests. */
6987 /* %%% These calls to eval() would benefit from using the Newton root,
6988 which will have already been computed when try.solve is called */
6989 eval(lhs, &lsqrt, 0, 0, 0, 0);
6990 eval(rhs, &rsqrt, 0, 0, 0, 0);
6991 /* printf("post-sqrt %17.15g = %s ?= %s = %17.15g\n", lsqrt, lhs, rhs, rsqrt); */
6992 if (lsqrt * rsqrt < 0) {
6993 if (debug_S) {
6994 printf(" then negating the right side so the signs agree\n");
6995 }
6996 symstrncat(rhs, ((symbol *) "n"), TS_ALLOC_R);
6997 }
6998
6999 } else if (op == 'W') {
7000
7001 /* The inverse of y=W(x) is x=w e^y, thus we solve this one by
7002 / changing "W(x)=RHS" by "x = RHS*e^RHS". This causes the RHS
7003 / to become more than twice as long. In theory if the LHS is of
7004 / the form [xWWWWW], TS_ALLOC_R would need to be something like
7005 / TS_ALLOC_L*2^(TS_ALLOC_L+1). We're not going to do that so
7006 / instead we declare TS_ALLOC_R to be something like 4*EXPR_ALLOC,
7007 / and we check to see if there is enough room to generate a
7008 / "RHS*e^RHS" here. */
7009 l1 = symstrlen(rhs) * 2 + 2;
7010 if (l1 >= TS_ALLOC_R) {
7011 /* We can't handle this 'W', so we're done solving. */
7012 gg = 0;
7013 } else {
7014 if (debug_S) {
7015 printf("transforming: ");
7016 eqn_print_infix(lhs, rhs);
7017 printf("\n by replacing 'W(a) = b' with 'a = b e^b'\n");
7018 }
7019 /* if (debug_S){printf(">> start: lhs=[%s], rhs=[%s]\n",lhs,rhs);} */
7020 /* Keep a copy of the RHS prior to manipulation */
7021 symstrncpy0(tmpc, rhs, TS_ALLOC_R);
7022 /* if (debug_S) { printf(">> step1 tmpc=[%s]\n", tmpc); } */
7023 /* Add the entire thing to the end, e.g. [1pq+] becomes [1pq+1pq+] */
7024 symstrncat(rhs, tmpc, TS_ALLOC_R);
7025 /* if (debug_S) { printf(">> step2 rhs=[%s]\n", rhs); } */
7026 /* Add an 'E' and a '*', so we have [1pq+1pq+E*] */
7027 symstrncat(rhs, (symbol *) "E*", TS_ALLOC_R);
7028 /* if (debug_S) { printf(">> step3 rhs=[%s]\n", rhs); } */
7029 /* Replace LHS with the argument, i.e. remove 'W' from the end */
7030 symstrncpy0(lhs, part1, TS_ALLOC_L);
7031 /* if (debug_S) { printf(">> result: lhs=[%s], rhs=[%s] len %d\n",
7032 lhs, rhs, l1); } */
7033 }
7034
7035 /* ------------------ Unhandled symbols ------------------- */
7036 /* Some symbols, e.g. sine and tangent, are not tested for at
7037 all. These functions have no inverse in RIES, so they cannot
7038 be moved to the right-hand-side. */
7039
7040 } else {
7041 /* We get here if the symbol 'op' is not one of the handled symbols */
7042 gg = 0;
7043 }
7044 }
7045
7046 if (l_out && r_out) {
7047 symstrncpy0(l_out, lhs, l_len);
7048 symstrncpy0(r_out, rhs, r_len);
7049 }
7050} /* End of try.solve */
7051
7052#define NEWTON_MAX_ITER 12
7053
7054/* newton performs Newton's method to determine the precise value of X
7055 for a given LHS and RHS to match. If the method does not converge
7056 or if there is an error the target value is returned instead in
7057 place of a root.
7058
7059 lhs - left-hand-side expression
7060 rhs - right-hand-side expression
7061 root - place to store the root
7062 diff_dx - place to store the derivative
7063 tags - place to put the tags (may be 0)
7064
7065 */
7066s16 newton(symbol * lhs, symbol * rhs, ries_val *root, ries_dif *diff_dx,
7067 ries_tgs *tags)
7068{
7069 ries_val rhs_val; ries_dif rhs_dx; ries_tgs rhs_tg;
7070 ries_val lhs_val; ries_dif lhs_dx; ries_tgs lhs_tg;
7071 ries_val curr, prev, prv2;
7072 s16 i, err, rhs_has_x;
7073
7074 /* Set default return values. */
7075 *root = g_target;
7076 /* If we return before we can compute a valid diff_dx, then we should
7077 treat it as a nonconverging case. We express that by returning a
7078 diff_dx of 0 */
7079 *diff_dx = 0;
7080 if (tags) { *tags = TYPE_NONE; }
7081
7082 rhs_has_x = (symstrsym(rhs, 'x') != 0);
7083
7084 /* first get the RHS value. */
7085 rhs_dx = 0; rhs_tg = TYPE_NONE; /* Assumed defaults */
7086 err = eval(rhs, &rhs_val, &rhs_dx, &rhs_tg, 0, 0); /* In newton() */
7087 if (err) {
7088 return err;
7089 }
7090 if (debug_n) {
7091 printf("newton RHS [%s] = ", rhs);
7092 spfg(k_nominal_digits, rhs_val); /* printf(fmt_g_nominal, rhs_val); */
7093 printf(" tag %x", rhs_tg);
7094 printf("\n");
7095 printf(" iterating LHS [%s]", lhs);
7096 if (rhs_has_x) {
7097 printf(" and RHS");
7098 }
7099 printf("...\n");
7100 }
7101
7102 curr = g_target; prev = curr - k_1; prv2 = prev - k_1;
7103 for(i=0; i<NEWTON_MAX_ITER; i++) {
7104 prv2 = prev; prev = curr;
7105 exec_x = curr;
7106 /* Get new LHS value */
7107 err = eval(lhs, &lhs_val, &lhs_dx, &lhs_tg, 0, 0); /* In newton() */
7108 if (err) {
7109 if (debug_n) { printf(" step %d, error from LHS eval.\n", i); }
7110 exec_x = g_target;
7111 return err;
7112 }
7113 if (lhs_dx == k_0) {
7114 if (debug_n) { printf(" step %d, zero LHS derivative.\n", i); }
7115 exec_x = g_target;
7116 return ERR_NEWTON_ZERO_DX;
7117 }
7118 if (debug_n) {
7119 printf(" step %d l=", i);
7120 spff(k_nominal_digits, lhs_val); /* printf(fmt_g_nom_fixed, lhs_val); */
7121 printf(" dl=");
7122 spfg(k_nominal_digits, lhs_dx); /* printf(fmt_g_nominal, lhs_dx); */
7123 printf(" tag %x", lhs_tg);
7124 printf("\n");
7125 }
7126 /* If there is an X on the RHS, we need to re-eval to get new RHS value */
7127 if (rhs_has_x) {
7128 err = eval(rhs, &rhs_val, &rhs_dx, &rhs_tg, 0, 0); /* In newton() */
7129 if (err) {
7130 if (debug_n) { printf(" step %d, error from RHS eval.\n", i); }
7131 exec_x = g_target;
7132 return err;
7133 }
7134 if (lhs_dx == k_0) {
7135 if (debug_n) { printf(" step %d, zero RHS derivative.\n", i); }
7136 exec_x = g_target;
7137 return ERR_NEWTON_ZERO_DX;
7138 }
7139 if (debug_n) {
7140 printf(" RHS r=");
7141 spff(k_nominal_digits, rhs_val); /* printf(fmt_g_nom_fixed, rhs_val); */
7142 printf(" dr=");
7143 spfg(k_nominal_digits, rhs_dx); /* printf(fmt_g_nominal, rhs_dx); */
7144 printf(" tag %x", rhs_tg);
7145 printf("\n");
7146 }
7147 }
7148 /* Note: To demonstrate that the derivatives don't need to be very
7149 accurate, you can substitute the following with:
7150
7151 curr = curr + ((rhs_val - lhs_val) * 1.001 / (lhs_dx - rhs_dx));
7152
7153 and RIES will report all the same results (but the -Dn option will
7154 show that it takes a few more iterations to converge on each root)
7155 */
7156 curr = curr + ((rhs_val - lhs_val) / (lhs_dx - rhs_dx));
7157 if (curr == prev) {
7158 /* we be done */
7159 i = NEWTON_MAX_ITER + 1;
7160 } else if (curr == prv2) {
7161 ries_dif margin;
7162 margin = (ries_dif) (FABS(curr-prev) * 9007199254740992.0 /* 2^53 */
7163 / FABS(curr));
7164 if (debug_n) {
7165 printf("newton cycle-2 loop, i == %d, margin == %g\n", i, margin);
7166 }
7167 if (margin <= 2.0) {
7168 /* Period-2 loop with amplitude 1 ULP (unit in the last place) */
7169 curr = prev; i = NEWTON_MAX_ITER + 1; /* Force success, exit loop */
7170 } else if ((i >= 6) && (margin <= 4.0)) {
7171 curr = prev; i = NEWTON_MAX_ITER + 1; /* Force success, exit loop */
7172 }
7173 }
7174 }
7175
7176 /* restore exec's target value. very important!! (-:*/
7177 exec_x = g_target;
7178
7179 /* Check for acceptably close convergence
7180 / older versions were:
7181 / if (fabs(curr - prev) == k_0)
7182 / if (fabs(curr - prev) < fabs(g_target * k_prune_deriv)) */
7183 if (curr == prev) {
7184 *root = curr;
7185 *diff_dx = lhs_dx - rhs_dx;
7186 if (tags) { *tags = rhs_tg; }
7187 if (debug_n) {
7188 printf(" converged precisely on ");
7189 spfg(k_nominal_digits, curr); /* printf(fmt_g_nominal, curr); */
7190 printf("\n");
7191 }
7192 return 0;
7193 } else if (FABS(curr - prev) < FABS(g_target * k_newton_settled)) {
7194 *root = curr;
7195 *diff_dx = lhs_dx - rhs_dx;
7196 if (tags) { *tags = rhs_tg; }
7197 if (debug_n) {
7198 printf(" converged on ");
7199 spfg(k_nominal_digits, curr); /* printf(fmt_g_nominal, curr); */
7200 printf(" by margin of ");
7201 spfg(k_nominal_digits, FABS(curr - prev)); /* printf(fmt_g_nominal, FABS(curr - prev)); */
7202 printf("\n");
7203 }
7204 return 0;
7205 }
7206
7207 if (debug_n) {
7208 printf(" did not converge (last delta = ");
7209 spfg(k_nominal_digits, curr - prev); /* printf(fmt_g_nominal, curr - prev); */
7210 printf(").\n");
7211 }
7212 return ERR_NEWTON_NO_CONVERGE;
7213} /* End of newton() */
7214
7215/* cv.simplify takes the same arguments as newton(). It looks at an
7216lhs and rhs that is suspected to be a new match.
7217 First it tries to remove redundant trailing operations added by
7218canon.val; for example if you run "ries 2.141592653 --canon-reduction
7219nr25 -l0" it will transform [x1+2/]=[p2/] into [x1+]=[p]. It does not try to
7220reorder things, so for example [xn2*]=[p2*n] would be left untouched.
7221 Then it runs newton() on the result, passing all the parameters
7222through to it.
7223 */
7224s16 cv_simplify(symbol * lhs, symbol * rhs, ries_val *root, ries_dif *diff_dx,
7225 ries_tgs *tags, int do_newton)
7226{
7227 s16 rv;
7228 int gg;
7229 s16 err;
7230
7231 if (debug_Q) {
7232 printf("cv.simplify: [%s]=[%s]\n", lhs, rhs);
7233 }
7234
7235 gg = 1;
7236 if (g_no_cv_simplify) {
7237 gg = 0;
7238 }
7239 while(gg) {
7240 gg = 0;
7241
7242 /* Bilateral cancellation */
7243 if (bothtrail(lhs, rhs, (symbol *) "2/")) {
7244 if (debug_Q) {
7245 printf(" remove shared trailing [2/]\n");
7246 }
7247 symstrclip(lhs, 2); symstrclip(rhs, 2); gg = 1;
7248 }
7249 if (bothtrail(lhs, rhs, (symbol *) "2*")) {
7250 if (debug_Q) {
7251 printf(" remove shared trailing [2*]\n");
7252 }
7253 symstrclip(lhs, 2); symstrclip(rhs, 2); gg = 1;
7254 }
7255 if (bothtrail(lhs, rhs, (symbol *) "r")) {
7256 if (debug_Q) {
7257 printf(" remove shared trailing [r]\n");
7258 }
7259 symstrclip(lhs, 1); symstrclip(rhs, 1); gg = 1;
7260 }
7261 if (bothtrail(lhs, rhs, (symbol *) "n")) {
7262 if (debug_Q) {
7263 printf(" remove shared trailing [n]\n");
7264 }
7265 symstrclip(lhs, 1); symstrclip(rhs, 1); gg = 1;
7266 }
7267
7268 /* Asymmetrical simplifications */
7269 if (symstrtrail(lhs,(symbol*)"nr") && symstrtrail(rhs,(symbol*)"n")) {
7270 /* [Anr]=[Bn] -> [Ar]=[B]
7271 This shows up in "ries 2.4284920346331 --canon-reduction nr25"
7272 which gives "1/-(ln(x)-1) = -(1-pi^2)" without this transformation,
7273 and "1/(ln(x)-1) = 1-pi^2" with it. */
7274 if (debug_Q) {
7275 printf(" replace [<a>nr]=[<b>n] with [<a>r]=[<b>]\n");
7276 }
7277 symstrclip(lhs, 2); symstrncat(lhs, (symbol *) "r", TS_ALLOC_L);
7278 symstrclip(rhs, 1); gg = 1;
7279 }
7280 if (symstrtrail(lhs,(symbol*)"n") && symstrtrail(rhs,(symbol*)"nr")) {
7281 /* [An]=[Bnr] -> [A]=[Br] */
7282 if (debug_Q) {
7283 printf(" replace [<a>n]=[<b>nr] with [<a>]=[<b>r]\n");
7284 }
7285 symstrclip(lhs, 1); symstrclip(rhs, 2);
7286 symstrncat(rhs, (symbol *) "r", TS_ALLOC_L); gg = 1;
7287 }
7288 if (symstrtrail(lhs,(symbol*)"rr")) {
7289 /* [Arr]=[B] -> [A]=[B]
7290 This shows up in "ries 2.50618 --canon-reduction r"
7291 which gives "1/(1/x^2) = 2 pi" without this transformation,
7292 and "x^2 = 2 pi" with it. */
7293 if (debug_Q) {
7294 printf(" replace [<a>rr]=[<b>] with [<a>]=[<b>]\n");
7295 }
7296 symstrclip(lhs, 2); gg = 1;
7297 }
7298 if (symstrtrail(rhs,(symbol*)"rr")) {
7299 /* [A]=[Brr] -> [A]=[B] */
7300 if (debug_Q) {
7301 printf(" replace [<a>]=[<b>rr] with [<a>]=[<b>]\n");
7302 }
7303 symstrclip(rhs, 2); gg = 1;
7304 }
7305 if (symstrtrail(lhs,(symbol*)"r2/") && symstrtrail(rhs,(symbol*)"r")) {
7306 /* [Ar2/]=[Br] -> [A2*]=[B]
7307 This shows up in "ries 2.4284920346331 --canon-reduction nr25" which
7308 gives "(1/((x/e)^pi)^2)/2 = 1/cospi(1/(4-1/pi))" without this
7309 transformation, and "2*((x/e)^pi)^2 = cospi(1/(4-1/pi))" with it. */
7310 if (debug_Q) {
7311 printf(" replace [<a>r2/]=[<b>r] with [<a>2*]=[<b>]\n");
7312 }
7313 symstrclip(lhs, 3); symstrncat(lhs, (symbol *) "2*", TS_ALLOC_L);
7314 symstrclip(rhs, 1); gg = 1;
7315 }
7316 if (symstrtrail(lhs,(symbol*)"r") && symstrtrail(rhs,(symbol*)"r2/")) {
7317 /* [Ar]=[Br2/] -> [A]=[B2*]
7318 This shows up in "ries 2.4284920346331 --canon-reduction nr25" which
7319 gives "1/-tanpi(sinpi(x-2)) = (1/cospi(2/e)^2)/2" without this
7320 transformation, and "-tanpi(sinpi(x-2)) = 2 cospi(2/e)^2" with it. */
7321 if (debug_Q) {
7322 printf(" replace [<a>r]=[<b>r2/] with [<a>]=[<b>2*]\n");
7323 }
7324 symstrclip(lhs, 1); symstrclip(rhs, 3);
7325 symstrncat(rhs, (symbol *) "2*", TS_ALLOC_L); gg = 1;
7326 }
7327 }
7328
7329 if (do_newton) {
7330 rv = newton(lhs, rhs, root, diff_dx, tags);
7331 } else {
7332 /* Do not perform Newton, but instead assume that lhs and rhs are already
7333 equal. This isn't currently used, but might be used by
7334 check.exact_match in the future. */
7335 *root = g_target;
7336 /* diff_dx will have been already set by caller */
7337 /* Call eval on the RHS to get the tags, and to discover any eval error. */
7338 err = eval(rhs, 0, 0, tags, 0, 0);
7339 return err;
7340 }
7341 return rv;
7342} /* End of cv.simplify */
7343
7344void defsym_used(symbol * expr)
7345{
7346 symbol * sym;
7347
7348 sym = expr;
7349 while(*sym) {
7350 if (sym_attrs[*sym].defn) {
7351 sym_attrs[*sym].def_needed = 1;
7352 }
7353 if (symstrsym(((symbol *) "CST"), *sym)) {
7354 used_trig = 1;
7355 }
7356 sym++;
7357 }
7358}
7359
7360/* AKA define_symbols, show_legend */
7361void describe_symbols(void)
7362{
7363 s16 sym;
7364 s16 lineleft, sl, clen;
7365 s16 going;
7366 const char * candidate;
7367 symbol csym = 0;
7368 int need_lf = 1;
7369
7370 going = 1; lineleft = LINELEFT_INIT;
7371 while (going) {
7372 going = 0;
7373 for(sym=0; sym<SYMBOL_RANGE; sym++) {
7374 if (sym_attrs[sym].def_needed) {
7375 if (sym_attrs[sym].def_given == 0) {
7376 going = 1;
7377 if (need_lf) {
7378 printf("\n");
7379 need_lf = 0;
7380 }
7381 }
7382 }
7383 }
7384
7385 if (going) {
7386 /* there's still one to print */
7387 candidate = 0; clen = 0;
7388 for(sym=0; sym<SYMBOL_RANGE; sym++) {
7389 if (sym_attrs[sym].def_needed) {
7390 if (sym_attrs[sym].def_given == 0) {
7391 sl = (s16) strlen(sym_attrs[sym].defn);
7392 if ( (sl > clen) && (sl < lineleft) ) {
7393 csym = (symbol) sym;
7394 candidate = sym_attrs[csym].defn;
7395 clen = (s16) strlen(candidate);
7396 }
7397 }
7398 }
7399 }
7400
7401 /* did we actually find one that fits? */
7402 if (candidate) {
7403 printf(" %s", sym_attrs[csym].defn);
7404 sym_attrs[csym].def_given = 1;
7405 lineleft = (s16) (lineleft - clen - 2);
7406 } else {
7407 printf("\n");
7408 lineleft = LINELEFT_INIT;
7409 }
7410 }
7411 }
7412
7413 if (lineleft < LINELEFT_INIT) {
7414 printf("\n");
7415 }
7416
7417 if (used_trig) {
7418 if (g_trig_scale_default) {
7419 /* In this case the functions are called "sinpi", etc. and are defined
7420 by the sym_defn[] strings */
7421 } else {
7422 /* Tell what units were used, special-case radians */
7423 printf(" For the trig functions, ");
7424 if (k_sincos_arg_scale == 1.0) {
7425 printf("2 pi");
7426 } else {
7427 printf("%g", dbl(2.0 * k_pi / k_sincos_arg_scale));
7428 }
7429 printf(" units are a full circle.\n");
7430 }
7431 }
7432}
7433
7434
7435/* This routine is meant to be used for *integer* values given as a double,
7436but formatted as if with the "%ld" format specifier. If the integer won't fit
7437in the given width, it then prints it using using a %e format instead. The
7438result is a char * pointing to a private buffer, which you need to use
7439before calling pf_intfloat_wid again.
7440 This example demonstrates its handling of width limits, rounding, etc.
7441
7442 #define TESTWIDMAX 14
7443 double x; int w;
7444 for(x=143.0; x<1.0e14; x*=-7.0) {
7445 for(w=7; w<TESTWIDMAX; w++) {
7446 printf("%*s ", w, pf_intfloat_wid(x, w));
7447 }
7448 printf("\n");
7449 }
7450
7451As you can see, a width of 7 characters only gives two significant digits
7452when the value is bigger than 9999999, or one significant digit for values
7453less than -999999. The routine is not designed for smaller widths. On the
7454high end, most C libraries will let you print as many digits as you want,
7455but widths bigger than about 20 don't give you much because "double" usually
7456only provides about 16 decimal digits of precision. */
7457char pfw_buf[40];
7458char * pf_intfloat_wid(stats_count x, int width)
7459{
7460 int i, w;
7461 char fmt1[FMT_STR_SIZE];
7462 char fmt2[FMT_STR_SIZE];
7463
7464 w = (x < 0) ? (width-1) : width;
7465 snprintf(fmt1, FMT_STR_SIZE, "%%.%dg", w);
7466 snprintf(fmt2, FMT_STR_SIZE, "%%.%de", w-6);
7467
7468 snprintf(pfw_buf, 40, fmt1, x);
7469 if (strchr(pfw_buf, 'e') || strchr(pfw_buf, 'E')) {
7470 snprintf(pfw_buf, 40, fmt2, x);
7471 } else if (strchr(pfw_buf, '.')) {
7472 for (i=0; pfw_buf[i]; i++) { }
7473 i--;
7474 while ((i > 0) && (pfw_buf[i] == '0')) {
7475 pfw_buf[i] = 0;
7476 i--;
7477 }
7478 if ((i > 0) && (pfw_buf[i] == '.')) {
7479 pfw_buf[i] = 0;
7480 }
7481 }
7482 return pfw_buf;
7483}
7484
7485int g_allow_slow_message;
7486
7487/* print.end generates the summary statistics that get printed at the
7488 end. Note that if the g_enable_output flag is not set, most of this
7489 does not get printed (such as when --find.expression is being used). */
7490void print_end(int exit_code)
7491{
7492 stats_count combos;
7493 long total_insert;
7494 time_flt tsec = gettime();
7495
7496 if (got_exact && (g_restrict_subexpr < TYPE_INT)) {
7497 printf(
7498 "\n"
7499 " NOTE: 'exact' match may result from floating-point roundoff error.\n"
7500 );
7501 }
7502
7503 if (debug_s) {
7504 printf(
7505 "\n"
7506 " NOTE: Some values will have lost significance in the last one or\n"
7507 " two digits due to round-off during intermediate calculations.\n"
7508 );
7509 }
7510
7511 if (g_enable_output && (out_expr_format <= OF_NORMAL)) {
7512 describe_symbols();
7513 }
7514
7515 total_insert = lhs_insert + rhs_insert;
7516 if (total_insert && g_enable_output) {
7517 printf("\n");
7518 printf(" --LHS-- --RHS-- -Total-\n");
7519 printf(" max complexity: %11d %11d %11d\n", lmax, rmax, lmax+rmax);
7520 printf(" dead-ends: %11s", pf_intfloat_wid(lhs_prune, 11));
7521 printf(" %11s", pf_intfloat_wid(rhs_prune, 11));
7522 printf(" %11s", pf_intfloat_wid(lhs_prune + rhs_prune, 11));
7523 printf(" Time: %.3f\n", tsec);
7524 printf(" expressions: %11s", pf_intfloat_wid(lhs_gen, 11));
7525 printf(" %11s", pf_intfloat_wid(rhs_gen, 11));
7526 printf(" %11s\n", pf_intfloat_wid(gen_total, 11));
7527 printf(" distinct: %11ld %11ld %11ld",
7528 lhs_insert, rhs_insert, total_insert);
7529 if (mem_used_KiB > 1024L) {
7530 printf(" Memory: %ldKiB\n", mem_used_KiB);
7531 } else {
7532 printf(" Memory: %ld B\n", mem_used_bytes);
7533 }
7534
7535 /* tell them how much work we did. */
7536 printf("\n");
7537 combos = ((stats_count) lhs_insert) * ((stats_count) rhs_insert);
7538 printf(" Total equations tested: %20s",
7539 pf_intfloat_wid(combos, 20));
7540 if (combos > 9999) {
7541 printf(" (%.4g)", (stats_count) combos);
7542 }
7543 printf("\n");
7544 }
7545
7546 if (exit_code) {
7547 exit(exit_code);
7548 }
7549} /* End of print.end */
7550
7551/* Cross-reference to the initialization functions:
7552/
7553/ validate_types: verifies that s16 is actually 16-bit, etc.
7554/ init_formats (aka check_precision, check_types): measures the precision
7555/ of the ries_val floating-point type
7556/ init_numerics: calculates the values of pi, e, phi, etc.
7557/
7558*/
7559
7560/* ieee.paranoia tries to check for IEEE-compliant compile options. Some optiona
7561 (such as those mentioned in the error printfs), make it hard to detect
7562 overflow, roundoff, etc. For background see:
7563
7564 www.gnu.org/software/libc/manual/html_node/Infinity-and-NaN.html
7565 gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
7566 */
7567void ieee_paranoia(void)
7568{
7569 ries_dif a1;
7570
7571#ifdef __FAST_MATH__
7572 fprintf(stderr,
7573 "RIES does not work when compiled with the --ffast-math option.\n");
7574 exit(-1);
7575#endif
7576
7577 /*
7578 Detect IEEE NaN compliance, by generating a NaN and trying to detect it in
7579 the manner supported by IEEE 754: a NaN is defined to be "unordered", i.e. it
7580 is not equal to, greater than, or less than anything, including even itself.
7581
7582 Note that in most GCC implementations, the C99 isnan() function exists but
7583 is merely defined by a macro, e.g.:
7584
7585 static __inline__ int __inline_isnanf( float __x ) { return __x != __x; }
7586
7587 We create a NaN by generating an oveflow value and subtracting it from
7588 itself.
7589 */
7590
7591 /* Generate an overflow value by starting with 2 and self-squaring 100
7592 times. This overflows if the exponent field is less than 100 bits. */
7593 for(k_d_inf=2.0,a1=1.0; a1<100.0; k_d_inf*=k_d_inf,a1++) { }
7594 k_d_ninf = 0.0 - k_d_inf;
7595
7596 /* Subtract this overflowed value from itself: inf-inf is NaN. */
7597 k_d_nan = k_d_inf - k_d_inf;
7598
7599 /* By definition, a NaN is not equal to itself. */
7600 if (k_d_nan != k_d_nan) {
7601 /* printf("detected NaN\n"); */
7602 } else {
7603 /* printf("did not detect NaN\n"); */
7604 fprintf(stderr,
7605"RIES does not work when compiled with options that prevent full IEEE 754\n"
7606"compliance, such as the GCC compiler options --ffast-math, -ffinite-math-only,\n"
7607"and -funsafe-math-optimizations.\n");
7608 exit(-1);
7609 }
7610}
7611
7612/* init.formats measures available precision and sets the formatting strings
7613 and other values used to format and print numbers.
7614 For initialization of constants like pi and e, see init_numerics */
7615void init_formats(void)
7616{
7617 float digits_usable, digits_nominal;
7618 ries_val a1, a2, k0, k1, k2;
7619 const char * gstr;
7620
7621 k0 = 0.0; k1 = 1.0; k2 = 2.0;
7622 /* The following loop looks for overflow and roundoff error, and counts
7623 the number of significant bits. There are several ways computer
7624 arithmetic can fail; this code tests three of them:
7625 - Normal signed integers will "wrap around" and become negative, failing
7626 the "a1>k0" test.
7627 - Floating-point numbers overflow to Infinity; this is caught by the
7628 "a1-a1==0" test (because Infinity-Infinity is a NaN).
7629 - Normal floating-point numbers eventually reach a point where they are
7630 so large that adding 1 to X then subtracting X rounds off to 0 (or
7631 perhaps 2 or a larger power of 2). The "a2-a1==k1" test catches this.
7632 - Arbitrary-precision types might be able to continue intil we fill
7633 available memory, or there might be some numerical oddity that our
7634 other tests miss. The "k_mantissa_bits<256" test catches these cases.
7635 - Dekker-style "double-double" arithmetic manages to pass all of the
7636 above tests when working with powers of 2. Therefore, rather than
7637 just doubling a1 each time through, every other time we add 2 so that
7638 when expressed in binary the mantissa has a "10101010..." pattern. */
7639 a1 = k2; /* 2 */
7640 a2 = a1 + k1; /* 3 */
7641 k_mantissa_bits = 1;
7642 rv_maxint = 1.0;
7643 while ((a2-a1 == k1) && (a1>k0) && (a1-a1==0) && (k_mantissa_bits < 666)) {
7644 a1 = a1 + a1; /* 4 20 84 340 */
7645 a2 = a1 + 1; /* 5 21 85 341 */
7646 k_mantissa_bits++;
7647 if ((a2-a1 == k1) && (a1>k0) && (a1-a1==0) && (k_mantissa_bits < 666)) {
7648 a1 = a1+a1+k2; /* 10 42 170 682 */
7649 a2 = a1 + 1; /* 11 43 171 683 */
7650 k_mantissa_bits++;
7651 }
7652 rv_maxint *= 2.0;
7653 }
7654 rv_maxint /= 4.0;
7655
7656 /* NOTE: Cannot use test debug_z flag here because args have not
7657 been parsed yet */
7658#ifdef RIES_DEBUG_FORMATS
7659 printf("init.formats: got %d mantissa bits\n", (int) k_mantissa_bits);
7660#endif
7661 /* Make sure the answer is "sane" */
7662 if ((int)k_mantissa_bits < 20) {
7663 printf("init.formats: Precision seems to be only %d binary bits; RIES cannot proceed.\n", (int) k_mantissa_bits);
7664 print_end(-1);
7665 }
7666 if (k_mantissa_bits > (float)(sizeof(ries_val))*9.0) {
7667 printf("init.formats: ries_val seems to have %d binary bits, but only uses %d bits!\n",
7668 (int) k_mantissa_bits, (int) (sizeof(ries_val) * 8));
7669 print_end(-1);
7670 }
7671 if (k_mantissa_bits > 256.0) {
7672 k_mantissa_bits = 256.0;
7673 }
7674 /* Compute size of the ULP (unit in the last place) for values in
7675 [0.5..1.0) */
7676 k_ulp = 0.5;
7677 for(a1=0.5; a1<k_mantissa_bits; a1+=1.0) {
7678 k_ulp *= 0.5;
7679 }
7680 digits_nominal = (k_mantissa_bits+1.0f) / 3.321928f;
7681 digits_usable = (k_mantissa_bits-3.0f) / 3.321928f;
7682 k_nominal_digits = (int)floor(digits_nominal + 1.0);
7683 k_usable_digits = (int)floor(digits_usable);
7684#ifdef RIES_DEBUG_FORMATS
7685 printf(" nominal: %f -> %d\n", digits_nominal, k_nominal_digits);
7686 printf(" usable: %f -> %d\n", digits_usable, k_usable_digits);
7687#endif
7688
7689 if (sizeof(long double) == sizeof(ries_val)) {
7690 gstr = "Lg";
7691 } else {
7692 gstr = "g";
7693 }
7694
7695 snprintf(fmt_g_nominal, FMT_STR_SIZE, "%%.%d%s", k_nominal_digits, gstr);
7696 snprintf(fmt_g_nom_fixed, FMT_STR_SIZE,
7697 "%%-%d.%d%s", k_nominal_digits+6, k_nominal_digits, gstr);
7698 snprintf(fmt_g_usable, FMT_STR_SIZE,
7699 "%%.%d%s", k_usable_digits, gstr);
7700 snprintf(fmt_g_usa_fixed, FMT_STR_SIZE,
7701 "%%-%d.%d%s", k_usable_digits+6, k_usable_digits, gstr);
7702 snprintf(fmt_g_diff, FMT_STR_SIZE, "%%.%dg", k_usable_digits-8);
7703 snprintf(fmt_g_dif_fixed, FMT_STR_SIZE,
7704 "%%-%d.%dg", k_usable_digits-2, k_usable_digits-8);
7705
7706#ifdef RIES_DEBUG_FORMATS
7707 printf("formats: fmt_g_nominal '%s', fmt_g_nom_fixed '%s'\n",
7708 fmt_g_nominal, fmt_g_nom_fixed);
7709 printf(" fmt_g_usable '%s', fmt_g_usa_fixed '%s'\n",
7710 fmt_g_usable, fmt_g_usa_fixed);
7711 printf(" fmt_g_diff '%s', fmt_g_dif_fixed '%s'\n",
7712 fmt_g_diff, fmt_g_dif_fixed);
7713#endif
7714} /* End of init.formats */
7715
7716/* check.exit checks to see if it's time to exit after a new match.
7717 If the g_exact.exit flag is set we exit because we're done. If not,
7718 then we test to see if best.match is negative. Once best.match becomes
7719 negative there is no chance of getting any more nonexact matches,
7720 and therefore this new match is the last useful output we'll get. */
7721void check_exit(int is_exact)
7722{
7723 if (is_exact && (g_restrict_subexpr == TYPE_INT) && g_exact_exit) {
7724 printf(" (Stopping now because -ie option was given.)\n");
7725 } else if (is_exact && (g_restrict_subexpr == TYPE_RAT) && g_exact_exit) {
7726 printf(" (Stopping now because -re option was given.)\n");
7727 } else if (is_exact && (g_restrict_subexpr == TYPE_CONS) && g_exact_exit) {
7728 printf(" (Stopping now because -ce option was given.)\n");
7729 } else if (is_exact && (k_max_match_dist == 0)) {
7730 printf(" (Stopping now because an exact match was found.)\n");
7731 } else if (is_exact && g_exact_exit) {
7732 printf(
7733" (Stopping now because --min-match-distance 0 or --max-match-distance 0\n"
7734" was given.)\n");
7735 } else if (best_match < g_min_matchsize) {
7736 /* Decide what number to print in the following message. If the
7737 --min.match-distance option was not given then g_min.matchsize will
7738 be zero; but k_min_best.match is positive in all cases.
7739 g_min.matchsize is zero then we're exiting because of
7740 subtracting k_min_best.match above. */
7741 ries_dif t = (k_min_best_match > g_min_matchsize) ?
7742 k_min_best_match : g_min_matchsize;
7743 printf(
7744 " (Stopping now because best match is within %7.3g of target value.)\n",
7745 t);
7746 } else if (g_num_matches >= g_max_matches) {
7747 if (g_num_matches == 1) {
7748 printf(" (Stopping now because 1 match was found.)\n");
7749 } else {
7750 printf(" (Stopping now because %ld matches were found.)\n",
7751 (long) g_num_matches);
7752 }
7753 } else {
7754 /* No exit condition was matched. */
7755 return;
7756 }
7757
7758 print_end(EXIT_NO_ERROR);
7759}
7760
7761/* unique.eqn takes an equation (in the form of LHS and RHS) and searches the
7762 list g.matches (which gets filled with all equations that we have decided
7763 to report as a match) */
7764int unique_eqn(symbol * lhs, symbol * rhs, int addit)
7765{
7766 symbol te[TS_ALLOC_R];
7767 symbol *where;
7768
7769 te[0] = 0;
7770 symstrncat(te, ((symbol *) " "), TS_ALLOC_R);
7771 symstrncat(te, lhs, TS_ALLOC_R);
7772 symstrncat(te, ((symbol *) "="), TS_ALLOC_R);
7773 symstrncat(te, rhs, TS_ALLOC_R);
7774 symstrncat(te, ((symbol *) " "), TS_ALLOC_R);
7775
7776 if ((where = symstrsymstr(g_matches, te)), where) {
7777 /* printf("unique.eqn: found '%s' at position %ld in '%s'\n",
7778 (char *) te, (long)(where-g_matches), (char *) g_matches); */
7779 return 0;
7780 }
7781 if (addit) {
7782 symstrncat(g_matches, te+1, (long) g_mtch_alloc);
7783 /* Carefully track memory usage */
7784 mem_used_bytes += (sizeof(symbol) * (symstrlen(te+1)+1));
7785 /* printf("unique.eqn: added '%s', result '%s'\n",
7786 (char *) te+1, (char *) g_matches); */
7787 }
7788 return 1;
7789}
7790
7791/* This field size is big enough for certain parts of a result output,
7792 including the "delta" part of an answer like "1.23456789 = T + 0.1234"
7793 and the "(1 part in 1023)" bit of a wide output */
7794#define REPORT_FIELD_SIZE 30
7795
7796/* Must be big enough for largest value of k_usable_digits */
7797#define FROOT_SIZE 40
7798
7799/* report.match does the formatting to print out a match. You can either
7800 supply an LHS and RHS that are already in the tree, or just one tree
7801 member and a pe (which you would do if reporting an exact match and
7802 don't want to insert the item) */
7803void report_match(symbol * lhs, symbol * rhs, symbol * exm,
7804 ries_val root, ries_dif delta, int did_newton)
7805{
7806 symbol * le;
7807 symbol * re;
7808 s16 i;
7809 char fval[REPORT_FIELD_SIZE]; /* formatted numerical value (before manual left-justify) */
7810 char froot[FROOT_SIZE]; /* formatted root of equation (value of X, not delta from T) */
7811 char * x_T_intro;
7812 s16 posn = 0; /* "cursor position" for column padding */
7813 int width; /* A column width */
7814 int justify_overflow = 0;
7815 symbol l_solved[TS_ALLOC_L]; symbol r_solved[TS_ALLOC_R];
7816 symbol l_escratch[TS_ALLOC_L]; symbol r_escratch[TS_ALLOC_R];
7817 char l_fscratch[F_ALLOC]; char r_fscratch[F_ALLOC * 2];
7818 char l_gscratch[MAX_ELEN * MAX_SYM_NAME_LEN];
7819 char r_gscratch[MAX_ELEN * MAX_SYM_NAME_LEN * 2]; /* *2 for try.solve */
7820 char * l_fmt;
7821 char * r_fmt;
7822 symbol ss;
7823 s16 err;
7824 s16 lf_len, rf_len;
7825 ries_val l_val, r_val; /* NOTE: None of these is used, not even in */
7826 ries_dif l_dx, r_dx; /* debug messages, so we could just pass 0's */
7827 ries_tgs l_tg, r_tg; /* to eval() */
7828
7829 /* ignore second and subsequent exact matches. */
7830 if ((delta == k_0) && got_exact) {
7831 return;
7832 }
7833
7834 /* If not doing refinement, prune based on the delta */
7835 if (!(g_refinement)) {
7836 stats_count i;
7837 ries_val * closeness;
7838 closeness = g_nr_deltas;
7839 for(i=0; i<g_num_matches; i++) {
7840 if (*closeness == delta) {
7841 if (debug_o) {
7842 printf("reject4 [%s]=[%s], duplicte delta value\n",
7843 (char *)lhs, (char *)rhs);
7844 }
7845 return;
7846 }
7847 closeness++;
7848 }
7849 /* It's a new delta value, save it. NOTE: other conditions later in
7850 / this routine may cause us to exit, in which case g_num_matches
7851 / won't get incremented and this saved delta will get overwritten
7852 / later, but that's okay because we only care about saving the
7853 / deltas of results that actually get reported. */
7854 *closeness = delta;
7855
7856 /* Carefully track memory usage */
7857 mem_used_bytes += sizeof(ries_val);
7858 }
7859
7860 /* If we are not doing refinement, then we should prune duplicate eqns */
7861 if(!(g_refinement)) {
7862 if (!(unique_eqn(lhs, rhs, 1))) {
7863 if (debug_o) {
7864 printf("reject1 [%s]=[%s], already reported\n",
7865 (char *)lhs, (char *)rhs);
7866 }
7867 return;
7868 }
7869 }
7870
7871 /* Set up le and re to point to the two parts of the equation. */
7872 if (lhs) {
7873 le = lhs;
7874 } else {
7875 le = exm;
7876 }
7877
7878 if (rhs) {
7879 re = rhs;
7880 } else {
7881 re = exm;
7882 }
7883
7884 if (g_solve_for_x) {
7885 if (debug_S || debug_s) {
7886 /* With either of these options we should print an extra blank line
7887 for readability */
7888 printf("\n");
7889 }
7890 }
7891
7892 /* Evaluate both sides, and show work if that option was given */
7893 if (debug_s) {
7894 printf("based on:\n");
7895 }
7896 /* These calls to eval() use the target value, thus displaying the
7897 discrepancy that existed before newton solving. */
7898 eval(le, &l_val, &l_dx, &l_tg, 0, debug_s); /* In report.match() */
7899 eval(re, &r_val, &r_dx, &r_tg, 0, debug_s);
7900 /* %%% is re_has_x used? */
7901
7902 if (debug_s) {
7903 printf("then equating ");
7904 expr_print_infix(le, 0);
7905 printf(" to ");
7906 expr_print_infix(re, 0);
7907 printf(",\n");
7908 printf(" ");
7909 if (did_newton) {
7910 printf("and solving for x by the Newton-Raphson method, ");
7911 }
7912 printf("I got\n");
7913 printf(" x = ");
7914 spfg(k_usable_digits, root); /* printf(fmt_g_usable, root); */
7915 printf(" = T ");
7916 if (delta < k_0) {
7917 printf("- %.6g\n", -delta);
7918 } else {
7919 printf("+ %.6g\n", delta);
7920 }
7921 }
7922
7923 if (g_solve_for_x) {
7924 /* Solve for X and point to resulting expressions */
7925 try_solve(le, re, l_solved, TS_ALLOC_L, r_solved, TS_ALLOC_R);
7926 le = l_solved; re = r_solved;
7927
7928 /* If not doing refinement, do the duplicate pruning again. This catches
7929 duplicates that were not duplicates in their pre-solved state. */
7930 if(!(g_refinement)) {
7931 if (!(unique_eqn(le, re, 1))) {
7932 if (debug_o) {
7933 printf("reject2 [%s]=[%s], already reported\n",
7934 (char *)lhs, (char *)rhs);
7935 } else if (debug_s) {
7936 printf("result rejected by unique_eqn() test.\n");
7937 }
7938 return;
7939 }
7940 }
7941 }
7942
7943 /* Format the LHS expression */
7944 lf_len = 0; err = 0; l_fmt = l_fscratch; l_fmt[0] = 0;
7945 if (out_expr_format == OF_POSTFIX) {
7946 err = postfix(le, (char *) l_escratch);
7947 l_fmt = (char *) l_escratch; lf_len = (s16) strlen(l_fmt);
7948 } else if ((out_expr_format == OF_CONDENSED)
7949 || (out_expr_format == OF_NORMAL)) {
7950 infix_preproc(le, l_escratch);
7951 err = infix_1(l_escratch, l_fscratch, &ss);
7952 if (out_expr_format == OF_CONDENSED) {
7953 l_fmt = l_fscratch; lf_len = (s16) strlen(l_fmt);
7954 } else {
7955 lf_len = infix_expand(l_fscratch, l_gscratch);
7956 l_fmt = l_gscratch;
7957 }
7958 } else if (out_expr_format == OF_FORTH) {
7959 lf_len = postfix_formatter(le, l_gscratch, MAX_ELEN * MAX_SYM_NAME_LEN);
7960 err = 0; l_fmt = l_gscratch;
7961 }
7962 if (err) {
7963 l_fmt[0] = 0;
7964 }
7965
7966 /* Format the RHS expression */
7967 rf_len = 0; err = 0; r_fmt = r_fscratch; r_fmt[0] = 0;
7968 if (out_expr_format == OF_POSTFIX) {
7969 err = postfix(re, (char *) r_escratch);
7970 r_fmt = (char *) r_escratch; rf_len = (s16) strlen(r_fmt);
7971 } else if ((out_expr_format == OF_CONDENSED)
7972 || (out_expr_format == OF_NORMAL)) {
7973 infix_preproc(re, r_escratch);
7974 err = infix_1(r_escratch, r_fscratch, &ss);
7975
7976 /* Now we have both sides reformatted to infix. If we are not doing
7977 refinement, we should add this to the list. */
7978 if(!(g_refinement)) {
7979 if (!(unique_eqn((symbol *)l_fscratch, (symbol *)r_fscratch, 1))) {
7980 if (debug_o) {
7981 printf("reject3 [%s]=[%s], already reported\n",
7982 (char *) l_fscratch, (char *) r_fscratch);
7983 } else if (debug_s) {
7984 printf("result rejected by unique_eqn() test.\n");
7985 }
7986 return;
7987 }
7988 }
7989
7990 if (out_expr_format == OF_CONDENSED) {
7991 r_fmt = r_fscratch; rf_len = (s16) strlen(r_fmt);
7992 } else {
7993 rf_len = infix_expand(r_fscratch, r_gscratch);
7994 r_fmt = r_gscratch;
7995 }
7996 } else if (out_expr_format == OF_FORTH) {
7997 rf_len = postfix_formatter(re, r_gscratch, MAX_ELEN * MAX_SYM_NAME_LEN * 2);
7998 err = 0; r_fmt = r_gscratch;
7999 }
8000 if (err) {
8001 r_fmt[0] = 0;
8002 }
8003
8004 if (debug_s) {
8005 printf("therefore:\n");
8006 }
8007
8008 /* Display the LHS and RHS as an equation, nicely centered. If either side
8009 can't fit we steal space from the other side. The amount of space we can
8010 use depends on the g.relative_x option (which affects the width of the
8011 "x+..." column). The default width values (44 and 40) are chosen to fit
8012 in 78 and 80 columns, respectively. If we go to a higher precision
8013 this will need to change significantly. */
8014 if (g_enable_output) {
8015 int l_pad, r_pad;
8016 int t_width, equ_width;
8017
8018#ifdef RIES_VAL_LDBL
8019 width = g_relative_x ? 44 : 37; /* Space allocated for LHS and RHS */
8020#else
8021 width = g_relative_x ? 44 : 40; /* Space allocated for LHS and RHS */
8022#endif
8023 equ_width = 5; /* one space on each end, " = " in the middle */
8024 t_width = width + equ_width; /* total width of our output */
8025
8026 /* compute padding (blank space) needed to make LHS and RHS fill their
8027 allotted space */
8028 /* In "solve for x" mode we give more to RHS */
8029 l_pad = (g_one_sided || g_solve_for_x) ? width/8 : width/2;
8030 r_pad = width - l_pad;
8031 l_pad -= lf_len; if (l_pad < 0) { l_pad = 0; }
8032 r_pad -= rf_len; if (r_pad < 0) { r_pad = 0; }
8033
8034 /* See how wide the result will be; if too wide, steal padding from
8035 the left, then from the right */
8036 width = l_pad + lf_len + equ_width + rf_len + r_pad;
8037 while ((width > t_width) && (l_pad > 0)) {
8038 l_pad--; width--;
8039 }
8040 while ((width > t_width) && (r_pad > 0)) {
8041 r_pad--; width--;
8042 }
8043 /* The result is bigger than t_width only when the equation genuinely won't
8044 fit in the space we want. Note this for use later. */
8045 justify_overflow = (width - t_width);
8046 if (justify_overflow < 0) {
8047 justify_overflow = 0;
8048 }
8049
8050 for(i=0; i<l_pad; i++) {
8051 printf(" ");
8052 }
8053 printf(" %s", l_fmt);
8054
8055 printf(" %s ", sym_attrs['='].sa_name);
8056
8057 printf("%s ", r_fmt);
8058 for(i=0; i<r_pad; i++) {
8059 printf(" ");
8060 }
8061 }
8062
8063 ries_spfg(froot, FROOT_SIZE, 0, k_usable_digits, root); /* sprintf(froot, fmt_g_usable, root); */
8064
8065 x_T_intro = (char *) "for x ";
8066 if (g_enable_output && g_wide_output) {
8067 /* Wide output mode: display the root first. This mode will have also
8068 set g.relative_x */
8069 printf("x = %-20s ", froot);
8070 x_T_intro = (char *) "";
8071 }
8072
8073 /* We put the "for x = " part in a fixed-size column doing the left-justify
8074 manually to avoid relying on an extension ("%*" parametrized-width
8075 format specifier) that is not available in old C compilers. */
8076
8077 if (delta == k_0) {
8078 if (g_enable_output) {
8079 printf("('exact' match)");
8080 }
8081 fval[0] = 0;
8082 posn = 15;
8083 got_exact = B_TRUE;
8084 } else if (g_enable_output && (!(g_relative_x))) {
8085 printf("for x = ");
8086 ries_spfg(fval, REPORT_FIELD_SIZE, 0, k_usable_digits, root); /* sprintf(fval, fmt_g_usable, root); */
8087 posn = (s16) (8 + strlen(fval));
8088 } else if (g_enable_output && (delta < k_0)) {
8089 /* Delta is negative */
8090 delta = - delta;
8091 printf("%s= T - ", x_T_intro);
8092 snprintf(fval, REPORT_FIELD_SIZE, "%.6g", delta);
8093 posn = (s16)(6 + strlen(x_T_intro) + strlen(fval) );
8094 } else if (g_enable_output) {
8095 /* Delta is positive */
8096 printf("%s= T + ", x_T_intro);
8097 snprintf(fval, REPORT_FIELD_SIZE, "%.6g", delta);
8098 posn = (s16)(6 + strlen(x_T_intro) + strlen(fval) );
8099 }
8100
8101 if (g_enable_output) {
8102 if (g_relative_x) {
8103 width = 12 + 6 + 5; /* "for x = T + ", 6 digits, decimal, "e-12" */
8104 } else {
8105 width = 8 + k_usable_digits + 6; /* "for x = ", digits, sign/dec/expon */
8106 }
8107 printf("%s", fval);
8108
8109 /* Add any extra chars that came from the equation being larger than its
8110 allocated space */
8111 posn = (s16)(posn + justify_overflow);
8112 /* Add blank space to fill the width */
8113 for(i=posn; i<width; i++) {
8114 printf(" ");
8115 }
8116
8117 /* Now we're past the printing of (exact match) and/or x, T, delta values
8118 and can proceed with additional columns */
8119 if (g_enable_output && g_wide_output) {
8120 /* Show delta as ratio with respect to T */
8121 ries_dif ratio;
8122 char temp[REPORT_FIELD_SIZE];
8123 ratio = 0;
8124 if (delta != 0) {
8125 ratio = (ries_dif) (FABS(g_target / delta));
8126 }
8127 if (delta == 0) {
8128 snprintf(temp, REPORT_FIELD_SIZE, "%s", "(1 part in infinity)");
8129 } else if (ratio < 100) {
8130 int r10, r1;
8131 r10 = (int) ((ratio * 10) + 0.5);
8132 r1 = r10 % 10; r10 = (r10-r1) / 10;
8133 snprintf(temp, REPORT_FIELD_SIZE, "(1 part in %d.%d)", r10, r1);
8134 } else if (ratio < 100000000) {
8135 snprintf(temp, REPORT_FIELD_SIZE,
8136 "(1 part in %d)", ((int) (ratio+0.5)));
8137 } else {
8138 snprintf(temp, REPORT_FIELD_SIZE, "(1 part in %.3e)", ratio);
8139 }
8140 printf("%-22s", temp);
8141 }
8142
8143 printf(" {%d}\n", complexity(le) + complexity(re));
8144 }
8145
8146 g_num_matches++;
8147
8148 defsym_used(le);
8149 defsym_used(re);
8150
8151 check_exit(delta==k_0);
8152} /* End of report.match() */
8153
8154/* matchscore = diff / dx */
8155/* diff = matchscore * dx */
8156
8157/* check.match reports a match if the RHS is within best.match * dx, where
8158 dx is the LHS's derivative. */
8159int check_match(expr * lhs, expr * rhs)
8160{
8161 ries_dif delta; /* The ratio diff / dx. This is how much bigger X
8162 would have to be to get a perfect match. */
8163 ries_dif score; /* Absolute value of delta */
8164 ries_val root;
8165 ries_dif total_deriv;
8166 s16 err;
8167
8168 if (debug_o) {
8169 printf("check_match [%s] ?= [%s]\n", lhs->sym, rhs->sym);
8170 }
8171
8172 /* start with a single step of Newton, which we can do easily because
8173 the x and dx values are already computed */
8174 total_deriv = lhs->der - rhs->der;
8175 if (total_deriv == k_0) {
8176 fprintf(stderr, "check_match got dx = 0!\n");
8177 return 0;
8178 }
8179 delta = (ries_dif) ((rhs->val - lhs->val) / total_deriv);
8180 score = fabs(delta);
8181 if (debug_o) {
8182 printf("check_match score %g, best_match %g, g_mms %g\n",
8183 score, dbl(best_match), g_min_matchsize);
8184 }
8185
8186 if ((score > best_match) || (score < g_min_matchsize)) {
8187 if (debug_o) {
8188 printf(" first score %g not good enough\n", score);
8189 }
8190 return 0;
8191 }
8192
8193 /* If we are not doing refinement, we can check this equation against
8194 those that have been reported.
8195 %%% This might actually slow things down! */
8196 if(!(g_refinement)) {
8197 if (!(unique_eqn(lhs->sym, rhs->sym, 0))) {
8198 if (debug_o) {
8199 printf(" already reported\n");
8200 }
8201 return 0;
8202 }
8203 }
8204
8205 /* We have a good candidate for a new match. Now we use Newton's
8206 method to get a more accurate score. From this point forward we only
8207 need the symstr part of the expression */
8208 {
8209 symbol lexpr[TS_ALLOC_L];
8210 symbol rexpr[TS_ALLOC_L];
8211
8212 symstrncpy0(lexpr, lhs->sym, TS_ALLOC_L);
8213 symstrncpy0(rexpr, rhs->sym, TS_ALLOC_L);
8214
8215 if (debug_q) {
8216 printf(" [%s] ~= [%s] (score %g), calling newton\n",
8217 lexpr, rexpr, score);
8218 }
8219
8220 /* cv.simplify removes things from both sides where possible, then
8221 calls newton */
8222 err = cv_simplify(lexpr, rexpr, &root, &total_deriv, 0, 1);
8223 if (err) {
8224 /* Eval got an error, or Newton did not converge: in either case
8225 we don't accept, because a failed Newton converge is probably
8226 a pathological case like sin(1/a) near a=0 */
8227 if (debug_q) {
8228 printf(" newton returned %d (%s)\n", err, err_string(err));
8229 }
8230 return 0;
8231 } else {
8232 if (debug_q) {
8233 printf("root: ");
8234 spfg(k_nominal_digits, root); /* printf(fmt_g_nominal, root); */
8235 printf("\n");
8236 }
8237 }
8238
8239 if (FABS(total_deriv) < k_vanished_dx) {
8240 if (debug_q) {
8241 printf(" derivative = %g is too small\n", total_deriv);
8242 }
8243 }
8244
8245 delta = (ries_dif) (root - g_target);
8246 if (debug_q) {
8247 printf("newton: target %g root %g delta %g\n", dbl(g_target),
8248 dbl(root), delta);
8249 }
8250 score = fabs(delta);
8251
8252 if (score == k_0) {
8253 /* Newton's method revealed that we have an exact match. We'll
8254 report it (in case it's our first exact match) but not adjust our
8255 report threshold. */
8256 if (debug_q) {
8257 printf(" exact match\n");
8258 }
8259
8260 report_match(lexpr, rexpr, 0, root, delta, 1);
8261 return 1;
8262 } else if (score < best_match) {
8263 if (debug_q) {
8264 printf(" new record %g\n", score);
8265 }
8266 report_match(lexpr, rexpr, 0, root, delta, 1);
8267 if(g_refinement) {
8268 /* The minus k_min_best.match is to avoid having lots of matches
8269 that beat each other only because of roundoff in the score
8270 calculation. This happens if you invoke e.g.
8271 "ries 0.434294481903252" */
8272 best_match = (score * 0.999) - k_min_best_match;
8273 if (debug_q) {
8274 printf(" lowering match threshold to %g\n",
8275 dbl(best_match));
8276 }
8277 }
8278 check_exit(0);
8279 return 1;
8280 } else if (debug_q) {
8281 printf(" post-newton score %g not good enough\n", score);
8282 }
8283 }
8284 return 0;
8285} /* End of check_match */
8286
8287
8288/* bt_first gives a pointer to the first node in the tree. Pass in the
8289 tree's root pointer. */
8290expr * bt_first(expr * it)
8291{
8292 while (it && it->left) {
8293 it = it->left;
8294 }
8295 return it;
8296}
8297
8298/* bt_depth returns the depth (number of links down from root) of an item. */
8299int bt_depth(expr * it)
8300{
8301 int rv;
8302
8303 /* Start at zero */
8304 rv = 0;
8305
8306 while(it) {
8307 rv++;
8308 it = it->up;
8309 }
8310
8311 return(rv);
8312}
8313
8314void bt_stats(void);
8315void bt_stats(void)
8316{
8317 long n;
8318 int tdepth;
8319
8320 expr * it;
8321 it = bt_first(lhs_root);
8322 n = 0; tdepth = 0;
8323 while(it) {
8324 if (debug_0) {
8325 printf("%8ld %10s {%3d} = ", n, it->sym, complexity(it->sym));
8326 spff(k_nominal_digits, it->val); /* printf(fmt_g_nom_fixed, it->val); */
8327 if (it->der) {
8328 printf(", dx = ");
8329 printf(fmt_g_diff, it->der); /* printf(fmt_g_nominal, it->der); */
8330 }
8331 printf("\n");
8332 }
8333
8334 /* Accumulate stats */
8335 tdepth += bt_depth(it);
8336
8337 it = bt_next(it);
8338 n++;
8339 }
8340
8341 printf("Current tree stats:\n");
8342 printf(" Nodes: %ld\n", n);
8343 printf(" Avg. Depth: %f\n", ((stats_count) tdepth) / ((stats_count) n));
8344}
8345
8346/* bt_prev traverses the list "backwards" to the next-smaller expression. */
8347expr * bt_prev(expr *it)
8348{
8349 expr *old;
8350
8351 /* if it has a left child it's relatively easy */
8352 if (it->left) {
8353 /* go down left, then down right to dead end */
8354 it = it->left;
8355 while (it->right) {
8356 it = it->right;
8357 }
8358 } else {
8359 /* here we have to traverse up until we get to a node from which we
8360 were the right. We also need to worry about going all the way off
8361 the top, which would mean we're done. */
8362 old = 0;
8363 while(it && (old == it->left)) {
8364 old = it;
8365 it = it->up;
8366 }
8367 }
8368
8369 return it;
8370}
8371
8372/* bt_next traverses the list to the next-greater expression. */
8373expr * bt_next(expr *it)
8374{
8375 expr *old;
8376
8377 /* if it has a right child it's relatively easy */
8378 if (it->right) {
8379 /* go down right, then down left to dead end */
8380 it = it->right;
8381 while (it->left) {
8382 it = it->left;
8383 }
8384 } else {
8385 /* here we have to traverse up until we get to a node from which we
8386 were the left. We also need to worry about going all the way off
8387 the top, which would mean we're done. */
8388 old = 0;
8389 while(it && (old == it->right)) {
8390 old = it;
8391 it = it->up;
8392 }
8393 }
8394
8395 return it;
8396}
8397
8398/*
8399check.sides looks for a match for a given expression. It checks
8400expressions of the opposite type (LHS or RHS) on either side (lower-
8401and higher-valued) of the supplied expression, and for each, calls
8402check.match.
8403 */
8404void check_sides(expr *it)
8405{
8406 expr * other;
8407 int cm_result;
8408
8409 /* "it" is the expression that is just now being added to the database.
8410 Check if it is an RHS or an LHS. */
8411
8412 if (it->der == k_0) {
8413 /* New way */
8414 /* we've got a RHS. Look on both sides for an LHS. If we find another
8415 RHS, we can stop because that RHS, by definition, will be a
8416 closer match to any LHS that lies beyond. */
8417 other = bt_prev(it);
8418 if (other && (other->der != k_0)) {
8419 /* "other" is an LHS, test it. */
8420 cm_result = check_match(other, it);
8421 if (cm_result && debug_q) {
8422 printf("(1st) LHS (left) = New RHS\n");
8423 }
8424 }
8425
8426 /* Now we do the same thing again, to the right this time. */
8427 other = bt_next(it);
8428 if (other && (other->der != k_0)) {
8429 cm_result = check_match(other, it);
8430 if (cm_result && debug_q) {
8431 printf("(1st) LHS (left) = New RHS\n");
8432 }
8433 }
8434
8435 } else {
8436 /* we've got an LHS */
8437 other = bt_prev(it);
8438 /* Check for an RHS, which always has a zero derivative term */
8439 if (other && (other->der == k_0)) {
8440 /* We have an RHS, check it */
8441 cm_result = check_match(it, other);
8442 if (cm_result && debug_q) {
8443 printf("New LHS = first RHS (left)\n");
8444 }
8445 }
8446 /* do the same thing again, to the right this time. */
8447 other = bt_next(it);
8448 if (other && (other->der == k_0)) {
8449 cm_result = check_match(it, other);
8450 if (cm_result && debug_q) {
8451 printf("New LHS = first RHS (right)\n");
8452 }
8453 }
8454 }
8455} /* end of check.sides */
8456
8457void check_exact_match(expr * it, ries_dif new_dx, pe *ex)
8458{
8459 symbol * lhs;
8460 symbol * rhs;
8461 ries_val x, xpe;
8462 ries_dif eps, total_deriv, delta, score;
8463
8464 lhs = rhs = 0;
8465
8466 if (new_dx == k_0) {
8467 /* new item is RHS. */
8468 if (it->der == k_0) {
8469 /* Tree item is RHS, too. We just discard in this case. */
8470 return;
8471 } else {
8472 /* Tree item is LHS... */
8473 if (fabs(it->der) < k_vanished_dx) {
8474 if (debug_q) {
8475 printf("chk_ex_match it->dx = %g is too small\n", it->der);
8476 }
8477 return;
8478 } else {
8479 lhs = it->sym;
8480 rhs = ex->sym;
8481 total_deriv = it->der;
8482 }
8483 }
8484 } else {
8485 /* new item is LHS. */
8486 if (it->der == k_0) {
8487 /* tree item is RHS... */
8488 if (fabs(new_dx) < k_vanished_dx) {
8489 if (debug_q) {
8490 printf("chk_ex_match dx = %g is too small\n", new_dx);
8491 }
8492 return;
8493 } else {
8494 lhs = ex->sym;
8495 rhs = it->sym;
8496 total_deriv = 0 - new_dx;
8497 }
8498 } else {
8499 /* Tree item is LHS too, discard. */
8500 return;
8501 /* %%% For x-on-both-sides, in this instance we will want to do
8502 a normal check.match, subtracting the two derivatives and
8503 rejecting if the result is too small (indicating an excessively
8504 high correlation or a tautology).
8505 Even if we get a match, we would still discard the new
8506 node afterwards because the existing node is more likely
8507 to yield equations with a lesser combined complexity. */
8508 }
8509 }
8510
8511 x = it->val; eps = ((ries_dif)x) * 1.0e-14; xpe = x + eps;
8512 if (x == xpe) {
8513 /* Answer is so small that we underflowed trying to compute epsilon */
8514 return;
8515 }
8516 if (total_deriv == 0) {
8517 return;
8518 }
8519 delta = eps / total_deriv;
8520 score = fabs(delta);
8521 if ((best_match > 0) && (score > best_match)) {
8522 return;
8523 }
8524 if (score < g_min_matchsize) {
8525 return;
8526 }
8527 if(!(g_refinement)) {
8528 if (!(unique_eqn(lhs, rhs, 0))) {
8529 return;
8530 }
8531 }
8532
8533 report_match(lhs, rhs, ex->sym, g_target, (ries_dif) k_0, 0);
8534}
8535
8536/* bt.insert adds an expression to the tree. The dx parameter
8537 is used to determine if it's an RHS or an LHS expression. */
8538s16 bt_insert(ries_val x, ries_dif dx, ries_tgs tg, pe *ex, s16 * res1)
8539{
8540 expr * it;
8541 s16 going, insert, fillin, i;
8542
8543 fillin = 0; going = 0; insert = 0; *res1 = 0;
8544 it = lhs_root;
8545 /* If there's a tree to descend, descend it. */
8546 if (it) {
8547 going = 1;
8548 insert = 1;
8549 } else {
8550 /* insert and copy first node */
8551 lhs_root = (expr *) my_alloc(sizeof(expr));
8552 if (lhs_root == 0) {
8553 return 1;
8554 }
8555 *res1 = 1;
8556 insert_count++;
8557 it = lhs_root;
8558 it->up = 0;
8559 going = 0; /* no descending to do */
8560 insert = 0; /* and we just inserted */
8561 fillin = 1; /* but we need to fill it in */
8562 }
8563 while(going) {
8564 if (it->val == x) {
8565 /* Exact match: there is already a node with the exact same value.
8566 We never insert another node with the same value, because by
8567 definition (due to the way we generate simpler expressions first)
8568 any equation made with the newly inserted node would be more complex
8569 than the existing equation we can get with the existing, simpler
8570 node.
8571 However, we do take the opportunity to report an exact match,
8572 checking the derivative of the side that contains X to avoid
8573 reporting a tautology. */
8574 going = 0;
8575 insert = 0;
8576
8577 check_exact_match(it, dx, ex); /* BT_CODE_MATCH */
8578 } else {
8579 /* no match yet: descend. */
8580 if (x < it->val) { /* BT_CODE_CMP */
8581 /* go to left child */
8582 if (it->left) {
8583 it = it->left;
8584 } else {
8585 /* no left: that means we insert here. */
8586 insert = -1;
8587 going = 0;
8588 }
8589 } else {
8590 /* go to right child */
8591 if (it->right) {
8592 it = it->right;
8593 } else {
8594 /* no right: that means we insert here. */
8595 insert = 1;
8596 going = 0;
8597 }
8598 }
8599 }
8600 }
8601
8602 if (insert) {
8603 expr *n;
8604
8605 n = (expr *) my_alloc(sizeof(expr));
8606 if (n == 0) {
8607 return 1;
8608 }
8609 *res1 = 1;
8610 insert_count++;
8611 if (insert > 0) {
8612 it->right = n;
8613 n->up = it;
8614 } else {
8615 it->left = n;
8616 n->up = it;
8617 }
8618 it = n;
8619 fillin = 1;
8620 }
8621 if (fillin) {
8622 /* copy the expression into the new node (BT_CODE_FILLIN) */
8623 it->val = x;
8624 it->der = dx;
8625 it->tags = tg;
8626 it->left = 0;
8627 it->right = 0;
8628 it->elen = ex->elen;
8629 for(i=0; i<=it->elen; i++) {
8630 it->sym[i] = ex->sym[i];
8631 }
8632 }
8633
8634 /* Last thing to do is to check for a new match. */
8635 if (insert) {
8636 check_sides(it); /* BT_CODE_INSERTED */
8637 }
8638
8639 return 0;
8640}
8641
8642s16 g_dbg_side;
8643
8644#define CANONVAL_NEGATE 1
8645#define CANONVAL_RECIPROCAL 2
8646#define CANONVAL_DIV2 4
8647#define CANONVAL_MUL2 8
8648int g_canon_ops;
8649
8650/*
8651
8652canon.val takes an expression which should be complete, and tries to
8653append additional operators to make its value fall within the range
8654[1.0,2.0).
8655
8656There are 4 types of transformations that we try to make, and they are
8657partly redundant: [r] and [2*] are only used if the value is in the
8658range (-1.0,1.0), but if [r] is used then the value will not be in
8659that range anymore, and [2*] will not trigger. This redundancy is
8660there to maximize the effectiveness of canon.val when the symbolset has
8661been restricted via the -S/-O/-N options.
8662
8663We check sym_attrs[*].count vs. sym_attrs[*].allowed, but don't bother
8664to update the counts because these are the last symbols that will be
8665added and we don't add more than one of any symbol.
8666
8667All parameters except muc_ptr are both inputs and return values.
8668*/
8669s16 canonval(
8670 pe * bpe, /* The expression to operate on */
8671 metastack * ms, /* The expression's metastack */
8672 ries_val *p_x, /* Value of the expression */
8673 ries_dif *p_dx, /* Derivative */
8674 ries_tgs *p_tg, /* tags */
8675 s16 *muc_ptr, /* Metastack undo count */
8676 s16 using_x /* Nonzero if we're currently generating expressions
8677 for the LHS tree. */
8678 )
8679{
8680 s16 muc = 0;
8681 s16 uc;
8682 s16 ip = bpe->elen;
8683 s16 sp;
8684 s16 exec_err;
8685 ries_val x;
8686 ries_dif dx;
8687 ries_tgs tg;
8688
8689 g_cv_calls++;
8690 if (g_canon_ops == 0) {
8691 *muc_ptr = muc;
8692 return 0;
8693 }
8694
8695 x = *p_x; dx = *p_dx; tg = *p_tg;
8696
8697 if (debug_F & g_dbg_side) {
8698 printf("canonval: ip %d, el %d [%s] val=%g, dv=%g\n",
8699 ip, bpe->elen, bpe->sym, dbl(x), dx);
8700 }
8701
8702 if ((g_canon_ops & CANONVAL_NEGATE)
8703 && (sym_attrs['n'].sa_ct < sym_attrs['n'].sa_alwd)
8704 && (x < 0.0) && (ip < MAX_ELEN))
8705 {
8706 /* Negate */
8707 bpe->sym[ip++] = 'n';
8708 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8709 if (exec_err) {
8710 *muc_ptr = muc;
8711 return exec_err;
8712 }
8713 x = ms_peek(ms, &dx, &tg, &sp);
8714 if (debug_F & g_dbg_side) {
8715 bpe->sym[ip] = 0;
8716 printf(" neg -> ip %d, el %d [%s] val=%g, dv=%g, tg %x\n",
8717 ip, bpe->elen, bpe->sym, dbl(x), dx, tg);
8718 }
8719 }
8720
8721 if ((g_canon_ops & CANONVAL_RECIPROCAL)
8722 && (sym_attrs['r'].sa_ct < sym_attrs['r'].sa_alwd)
8723 && (x*x < 1.0) /* faster way to test if (fabs(x) < 1.0) */
8724 && (ip < MAX_ELEN))
8725 {
8726 /* Take the reciprocal */
8727 bpe->sym[ip++] = 'r';
8728 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8729 if (exec_err) {
8730 *muc_ptr = muc;
8731 return exec_err;
8732 }
8733 x = ms_peek(ms, &dx, &tg, &sp);
8734 if (debug_F & g_dbg_side) {
8735 bpe->sym[ip] = 0;
8736 printf(" recip -> ip %d, el %d [%s] val=%g, dv=%g, tg %x\n",
8737 ip, bpe->elen, bpe->sym, dbl(x), dx, tg);
8738 }
8739 }
8740
8741 if ((g_canon_ops & CANONVAL_DIV2)
8742 && (sym_attrs['/'].sa_ct < sym_attrs['/'].sa_alwd)
8743 && (sym_attrs['2'].sa_ct < sym_attrs['2'].sa_alwd)
8744 && (x*x >= 4.0) /* faster way to test if (fabs(x) >= 2.0) */
8745 && (ip+1 < MAX_ELEN))
8746 {
8747 /* Divide by 2 */
8748 bpe->sym[ip++] = '2';
8749 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8750 if (exec_err) {
8751 *muc_ptr = muc;
8752 return exec_err;
8753 }
8754 bpe->sym[ip++] = '/';
8755 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8756 if (exec_err) {
8757 *muc_ptr = muc;
8758 return exec_err;
8759 }
8760 x = ms_peek(ms, &dx, &sp, &tg);
8761 if (debug_F & g_dbg_side) {
8762 bpe->sym[ip] = 0;
8763 printf(" 2/ -> ip %d, el %d [%s] val=%g, dv=%g, tg %x\n",
8764 ip, bpe->elen, bpe->sym, dbl(x), dx, tg);
8765 }
8766 }
8767
8768 if ((g_canon_ops & CANONVAL_MUL2)
8769 && (sym_attrs['*'].sa_ct < sym_attrs['*'].sa_alwd)
8770 && (sym_attrs['2'].sa_ct < sym_attrs['2'].sa_alwd)
8771 && (x*x < 1.0) /* faster way to test if (fabs(x) < 1.0) */
8772 && (ip+1 < MAX_ELEN))
8773 {
8774 /* Multiply by 2 */
8775 bpe->sym[ip++] = '2';
8776 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8777 if (exec_err) {
8778 *muc_ptr = muc;
8779 return exec_err;
8780 }
8781 bpe->sym[ip++] = '*';
8782 exec_err = exec(ms, bpe->sym[ip-1], &uc, using_x); muc=(s16)(muc+uc);
8783 if (exec_err) {
8784 *muc_ptr = muc;
8785 return exec_err;
8786 }
8787 x = ms_peek(ms, &dx, &sp, &tg);
8788 if (debug_F & g_dbg_side) {
8789 bpe->sym[ip] = 0;
8790 printf(" 2* -> ip %d, el %d [%s] val=%g, dv=%g, tg %x\n",
8791 ip, bpe->elen, bpe->sym, dbl(x), dx, tg);
8792 }
8793 }
8794
8795 /* We made it through the exec()s without error, so now we'll save the
8796 results of our calculations. */
8797 bpe->elen = ip;
8798 *p_x = x; *p_dx = dx; *p_tg = tg;
8799 *muc_ptr = muc;
8800 return 0;
8801} /* End of canon.val */
8802
8803void decanon(metastack * ms, s16 muc)
8804{
8805 while(muc) {
8806 ms_undo(ms);
8807 muc--;
8808 }
8809}
8810
8811/* ge_2 is the core code for generating expressions from a form.
8812
8813 base -----bpe-----
8814 comp elen syms
8815 ab 0 0 -
8816 ab 10 1 1
8817 ab 17 2 1l
8818 ab 17 2 1n
8819 ab 13 1 2
8820 ab 20 2 2r
8821 ab 20 2 2q
8822 ab 20 2 2l
8823*/
8824stats_count ge_2(
8825 form *base,
8826 pe *bpe,
8827 s16 e_minw, s16 e_maxw,
8828 metastack *ms,
8829 s16 using_x /* Nonzero if we're currently generating expressions
8830 for the LHS tree. */
8831 )
8832{
8833 symbol seft, sym;
8834 symbol *syms;
8835 s16 ns;
8836 s16 in_cpx; /* Complexity of input partial expression */
8837 s16 rminw, rmaxw;
8838 s16 ip;
8839 stats_count n;
8840 s16 recurse;
8841 attr_bits atts;
8842 s16 muc; /* metastack undo count */
8843 ries_val curtop; ries_dif ctdx; ries_tgs cttg;
8844 s16 err;
8845 s16 cur_sp;
8846
8847 n = 0; muc = 0;
8848
8849 ip = bpe->elen;
8850
8851 /* ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' "
8852 Exec symbol and handle errors
8853 On entry, ge.2() usually has a symbol that was just added by the parent
8854 instance of ge.2(). We start by exec'ing this symbol, then return if any
8855 type of error happened.
8856 ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " */
8857
8858 if (ip > 0) {
8859 g_exec_calls++;
8860 /* if there are errors like [0/] or [1nq], we'll return right away,
8861 thereby pruning */
8862 err = exec(ms, bpe->sym[ip-1], &muc, using_x);
8863 if (err) {
8864 if (debug_A & g_dbg_side) {
8865 bpe->sym[ip] = 0;
8866 printf("prune partial exec error [%s) got %d\n", bpe->sym, err);
8867 }
8868 while(muc) { ms_undo(ms); muc--; }
8869 return 0;
8870 }
8871
8872 /* Now find out what the current value on the stack is */
8873 curtop = ms_peek(ms, &ctdx, &cttg, &cur_sp);
8874
8875 /* We can always prune zero subexpressions. Any solution that
8876 contains a zero subexpression can be reduced to a simpler
8877 solution that does not contain a zero subexpression. */
8878 if (curtop == k_0) {
8879 if (debug_B & g_dbg_side) {
8880 bpe->sym[ip] = 0;
8881 printf("prune partial zero [%s) = ", bpe->sym);
8882 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
8883 printf("\n");
8884 }
8885 while(muc) { ms_undo(ms); muc--; }
8886 prune_count += 1.0;
8887 return 0;
8888 }
8889
8890 /* Prune non-integer subexpressions if the -i option was given. */
8891 if (g_restrict_subexpr == TYPE_INT) {
8892 if (!TAG_INT_P(cttg)) {
8893 if (debug_C & g_dbg_side) {
8894 bpe->sym[ip] = 0;
8895 printf("prune partial noninteger [%s) = ", bpe->sym);
8896 spfg(k_nominal_digits, curtop); /* printf(fmt_g_nominal, curtop); */
8897 printf(" %s", tagname(cttg));
8898 printf("\n");
8899 }
8900 while(muc) { ms_undo(ms); muc--; }
8901 prune_count += 1.0;
8902 return 0;
8903 }
8904 }
8905
8906 /* Similar pruning for less-restrictive values of g_restrict_subexpr.
8907 If an option like "-a" is used without modification, this test is
8908 redundant because the other restrictions e.g. g_restrict_exponents
8909 and the symbolset ensure that functions results remain within the
8910 restricted class. */
8911 if (cttg < g_restrict_subexpr) {
8912 if (debug_C & g_dbg_side) {
8913 bpe->sym[ip] = 0;
8914 printf("prune partial g_restr_sub [%s) = ", bpe->sym);
8915 spfg(k_nominal_digits, curtop);
8916 printf(" %s", tagname(cttg));
8917 printf("\n");
8918 }
8919 while(muc) { ms_undo(ms); muc--; }
8920 prune_count += 1.0;
8921 return 0;
8922 }
8923
8924 /* %%% here we could do a bt_find to search for the value curtop, and
8925 if an exact match is found, confirm that the derivative is also equal,
8926 then check if the trailing N opcodes of our PE are equal to that
8927 found (if any). If not, our PE is a redundant and possibly more
8928 complex way to generate a value, and can be pruned. This should be
8929 a significant optimization. It covers the same ground as the AM_
8930 rules, but catches many cases they miss (like multiple equivalent
8931 sums: 37+, 28+, 19+, 136++, 136n-+, and on and on... */
8932
8933 /* %%% this could be done more efficiently inside exec() */
8934 /* Any subexpression that overflows either in value or in the
8935 derivative causes pruning. */
8936 if ((curtop >= p_ovr) || (curtop <= n_ovr)) {
8937 if (debug_D & g_dbg_side) {
8938 bpe->sym[ip] = 0; /* Do not display not-yet-exec'd symbols */
8939 printf("prune partial overflow [%s) = ", bpe->sym);
8940 spfg(k_nominal_digits, curtop); /* printf(fmt_g_nominal, curtop); */
8941 printf("\n");
8942 }
8943 while(muc) { ms_undo(ms); muc--; }
8944 prune_count += 1.0;
8945 return 0;
8946 }
8947
8948 /* ignore any LHS partial-expressions with nonzero but very small
8949 derivative (tautology problem from roundoff error) */
8950 if (using_x) {
8951 /* formerly tested "(fabs(ctdx) > k_0) && (fabs(ctdx) < k_prune_deriv)"
8952 pp. 20111228 was "(fabs(ctdx)/(1.0 + fabs(curtop)) < k_prune_deriv)"
8953 Test the current top of stack for bogus derivative. We have to
8954 test ctdx != 0 to ensure we don't prune constants, like pruning the
8955 "2" in "x2+" before the "+" has been executed. The check for
8956 full-expression tautologies, e.g. pruning "x^2-x*x", happens
8957 in the next block. */
8958 if ( (ctdx != k_0) && (FABS(ctdx)/(1.0 + FABS(curtop)) < k_vanished_dx) )
8959 {
8960 bpe->sym[ip] = 0; /* Do not display not-yet-exec'd symbols */
8961 if (debug_B & g_dbg_side) {
8962 printf("prune partial dx~=0 [%s) = ", bpe->sym);
8963 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
8964 printf(", d/dx = ");
8965 printf(fmt_g_diff, ctdx);
8966 printf(" %s", tagname(cttg));
8967 printf("\n");
8968 }
8969 while(muc) { ms_undo(ms); muc--; }
8970 prune_count += 1.0;
8971 return 0;
8972 }
8973
8974 /* Ignore complete LHS expressions with zero derivative (tautology
8975 problem). This catches all normal non-roundoff tautologies, like
8976 "-x/x" and "(x-4)-(x-1)" */
8977 if ( (cur_sp == 0) && (FABS(ctdx)/(1.0 + FABS(curtop)) < k_vanished_dx) )
8978 {
8979 bpe->sym[ip] = 0; /* Do not display not-yet-exec'd symbols */
8980 if (debug_B & g_dbg_side) {
8981 printf("prune full.1 dx~=0 [%s] = ", bpe->sym);
8982 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
8983 printf(", d/dx = ");
8984 printf(fmt_g_diff, ctdx);
8985 printf(" %s", tagname(cttg));
8986 printf("\n");
8987 }
8988 while(muc) { ms_undo(ms); muc--; }
8989 prune_count += 1.0;
8990 return 0;
8991 }
8992 } /* End of "if (using_x)" */
8993 } /* End of "if (ip > 0)" */
8994
8995 /* ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' "
8996 Handling complete expressions
8997 If the just-exec'd symbol makes the expression complete, we try to insert
8998 it in the database.
8999 ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " */
9000
9001 if (ip >= base->flen) {
9002 s16 res1;
9003 /* it's now as long as it can get. */
9004
9005 /* We still have values of curtop, dx, and cur_sp from calling
9006 ms_peek() above */
9007 bpe->sym[ip] = 0; /* Needed by bt.insert */
9008
9009 /* Implement the --find.expression option */
9010 if (g_num_find_expr) {
9011 s16 i;
9012 for(i=0; i<g_num_find_expr; i++) {
9013 if(symstrcmp(bpe->sym, g_find_expr[i]) == 0) {
9014 printf(" [%s] = ", bpe->sym);
9015 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
9016 if (ctdx != 0) {
9017 printf(", d/dx = %g", ctdx);
9018 }
9019 printf(" %s", tagname(cttg));
9020 printf(", complexity = {%d}\n", bpe->cplx);
9021 }
9022 }
9023 }
9024
9025 if (using_x && (fabs(ctdx) < k_vanished_dx)) {
9026 if (debug_B & g_dbg_side) {
9027 printf("prune full.2 dx~=0 [%s) = ", bpe->sym);
9028 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
9029 printf(", d/dx = ");
9030 printf(fmt_g_diff, ctdx);
9031 printf(" %s", tagname(cttg));
9032 printf("\n");
9033 }
9034 while(muc) { ms_undo(ms); muc--; }
9035 prune_count += 1.0;
9036 return 0;
9037 } else if (curtop < g_min_equ_val) {
9038 if (debug_B & g_dbg_side) {
9039 printf("prune equval [%s) = ", bpe->sym);
9040 spfg(k_usable_digits, curtop);
9041 printf(" too low\n");
9042 }
9043 while(muc) { ms_undo(ms); muc--; }
9044 prune_count += 1.0;
9045 return 0;
9046 } else if (curtop > g_max_equ_val) {
9047 if (debug_B & g_dbg_side) {
9048 printf("prune equval [%s) = ", bpe->sym);
9049 spfg(k_usable_digits, curtop);
9050 printf(" too high\n");
9051 }
9052 while(muc) { ms_undo(ms); muc--; }
9053 prune_count += 1.0;
9054 return 0;
9055 } else {
9056 s16 uc; /* Metastack undo count for canonval operation */
9057 s16 oip;
9058 oip = bpe->elen;
9059 /* Bring value into canonical range */
9060 err = canonval(bpe, ms, &curtop, &ctdx, &cttg, &uc, using_x);
9061 if (err) {
9062 if (debug_G & g_dbg_side) {
9063 bpe->sym[ip] = 0;
9064 printf("prune canonval exec error [%s) got %d\n", bpe->sym, err);
9065 }
9066 while(uc) { ms_undo(ms); uc--; }
9067 return 0; /* Don't count this as a valid generated expression. */
9068 }
9069 /* Looks good so far, now try to insert in tree */
9070 bpe->sym[bpe->elen] = 0; /* Needed by bt.insert */
9071 if (bt_insert(curtop, ctdx, cttg, bpe, &res1)) { /* this is in ge_2 */
9072 fprintf(stderr, "%s: Out of memory\n", g_argv0);
9073 print_end(1);
9074 }
9075
9076 if (res1 == 0) {
9077 if (debug_E & g_dbg_side) {
9078 printf("reject [%s] = ", bpe->sym);
9079 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
9080 printf(" (duplicate value)\n");
9081 }
9082 /* We do not undo and return 0 here, because we want to count this as a
9083 "generated value". So we fall through to the "return 1;" below. */
9084 } else if (debug_G & g_dbg_side) {
9085 /* We do this debug print in infix, because it's so useful for things
9086 like OEIS sequence A005245. */
9087 printf("ge_2 inserted ");
9088 expr_print_infix(bpe->sym, 0);
9089 printf(" = ");
9090 spfg(k_usable_digits, curtop); /* printf(fmt_g_usable, curtop); */
9091 if (ctdx != 0) {
9092 printf(", d/dx = ");
9093 printf(fmt_g_diff, ctdx);
9094 }
9095 printf(" %s", tagname(cttg));
9096 printf(" {%d}\n", bpe->cplx);
9097 }
9098
9099 /* Undo the canonval ops */
9100 decanon(ms, uc);
9101 bpe->elen = oip;
9102 }
9103
9104 /* undo stack manipulation and return */
9105 while(muc) { ms_undo(ms); muc--; }
9106 return 1; /* We generated 1 item */
9107 } /* End of "if (ip >= base->flen)" */
9108
9109 /* ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' "
9110 Generate and add the next symbol(s)
9111 We reach here if we have an incomplete expression. This is also the first
9112 code executed in the case where there is no expression yet (initial call
9113 from ge.1())
9114 ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " */
9115
9116 /* get seft and comp */
9117 seft = base->sym[ip];
9118 in_cpx = bpe->cplx;
9119
9120 /* set up our variables for generation.
9121 Here we get a pointer to the list of symbols of the seft for this
9122 position in the form.
9123 %%% solve-for-x: If we're generating LHS's, this list will be either
9124 the LHS symlist or the RHS list, depending on the value of cur_sp */
9125 syms = 0; ns = 0;
9126 switch(seft) {
9127 case 'a':
9128 syms = g_asym; ns = n_asym;
9129 break;
9130 case 'b':
9131 syms = g_bsym; ns = n_bsym;
9132 break;
9133 case 'c':
9134 syms = g_csym; ns = n_csym;
9135 break;
9136 }
9137
9138 /* find out how much weight might be added to complete this expression.
9139 these stats were pre-computed at the start of the form (by ge.1) */
9140 rminw = bpe->pe_rminw[ip+1];
9141 rmaxw = bpe->pe_rmaxw[ip+1];
9142
9143 /* ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' "
9144 Prune pattern recognition
9145 Here we look at the recentmost few symbols and match them against all
9146 the special patterns used for pruning.
9147 ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " */
9148
9149 /* calculate the attributes for the symbols we have so far */
9150 if (ip > 0) {
9151 if (debug_H & g_dbg_side) {
9152 bpe->sym[ip] = 0;
9153 printf("attributes for [%s)%c: ", bpe->sym, seft);
9154 }
9155 }
9156 atts = using_x ? 0 : AM_RHS;
9157 /* no debug print for using_x because it's pretty obvious */
9158
9159 if (ip > 2) {
9160 /* Three-symbol patterns */
9161 if ( (base->sym[ip-1] == 'a')
9162 && (base->sym[ip-2] == 'c')
9163 && (base->sym[ip-3] == 'a') ) {
9164 /* We have ...aca */
9165 if (debug_H & g_dbg_side) {
9166 printf(" (%c%c%c)", bpe->sym[ip-3], bpe->sym[ip-2], bpe->sym[ip-1]);
9167 }
9168 /* KxK rule is true if we do K * K with the same constant both times. */
9169 if (bpe->sym[ip-1] == bpe->sym[ip-3]) {
9170 if (bpe->sym[ip-2] == '*') {
9171 atts |= AM_KxK;
9172 if (debug_H & g_dbg_side) { printf(" K*K"); }
9173 } else if (bpe->sym[ip-2] == '+') {
9174 atts |= AM_KpK;
9175 if (debug_H & g_dbg_side) { printf(" K+K"); }
9176 }
9177 }
9178 }
9179 }
9180
9181 if (ip > 1) {
9182 /* two-symbol patterns */
9183
9184 if (seft == 'c') {
9185 s16 a1i;
9186
9187 /* next symbol will be a binary operator; look at arg1 */
9188 a1i = base->arg1[ip];
9189 if (a1i >= 0) {
9190 if (bpe->sym[a1i] == 'e') {
9191 atts |= AM_a1_e;
9192 if (debug_H & g_dbg_side) { printf(" e..<op>"); }
9193 } else if (bpe->sym[a1i] == '1') {
9194 atts |= AM_a1_1;
9195 if (debug_H & g_dbg_side) { printf(" 1..<op>"); }
9196 } else if (bpe->sym[a1i] == 'r') {
9197 atts |= AM_a1_r;
9198 if (debug_H & g_dbg_side) { printf(" r..<op>"); }
9199 }
9200 }
9201 }
9202
9203 /* currently, all two-symbol patterns are for (aa) forms */
9204 if ((base->sym[ip-1] == 'a')
9205 && (base->sym[ip-2] == 'a')) {
9206 if (debug_H & g_dbg_side) {
9207 printf(" (%c%c)", bpe->sym[ip-2], bpe->sym[ip-1]);
9208 }
9209
9210 /* KK rule is true if the same constant occurs twice in a row. */
9211 if (bpe->sym[ip-1] == bpe->sym[ip-2]) {
9212 atts |= AM_KK;
9213 if (debug_H & g_dbg_side) { printf(" KK"); }
9214 }
9215
9216 /* 55 rule is true if both constants are integers less than or equal
9217 * to 5. */
9218 if ((bpe->sym[ip-1] < '6')
9219 && (bpe->sym[ip-2] < '6')) {
9220 atts |= AM_55;
9221 if (debug_H & g_dbg_side) { printf(" 55"); }
9222 }
9223
9224 /* 1K rule is true if first constant is 1 */
9225 if (bpe->sym[ip-2] == '1') {
9226 atts |= AM_1K;
9227 if (debug_H & g_dbg_side) { printf(" 1K"); }
9228 }
9229
9230 /* jK rule: true if smaller constant is followed by larger constant.
9231 * For these purposes, the noninteger constants are considered
9232 * larger than all the integers. (This can be changed if necessary
9233 * by adding an indirection array defining symbol sequence, or by
9234 * using the symbol weights as a sequencing measure -- but for now,
9235 * it works fine this way.) */
9236 if (bpe->sym[ip-1] > bpe->sym[ip-2]) {
9237 atts |= AM_jK;
9238 if (debug_H & g_dbg_side) { printf(" jK"); }
9239 }
9240 }
9241 }
9242
9243 if (ip > 0) {
9244 /* one-symbol patterns */
9245
9246#if 0
9247 if (debug_H & g_dbg_side) {
9248 printf(" (%c)", bpe->sym[ip-1]);
9249 }
9250 if (bpe->sym[ip-1] == '1') {
9251 atts |= AM_1;
9252 if (debug_H & g_dbg_side) { printf(" 1"); }
9253 } else if (bpe->sym[ip-1] == '2') {
9254 atts |= AM_2;
9255 if (debug_H & g_dbg_side) { printf(" 2"); }
9256 } else if (bpe->sym[ip-1] == 'n') {
9257 atts |= AM_n;
9258 if (debug_H & g_dbg_side) { printf(" n"); }
9259 } else if (bpe->sym[ip-1] == 'r') {
9260 atts |= AM_r;
9261 if (debug_H & g_dbg_side) { printf(" r"); }
9262 } else if (bpe->sym[ip-1] == 'l') {
9263 atts |= AM_l;
9264 if (debug_H & g_dbg_side) { printf(" l"); }
9265 } else if (bpe->sym[ip-1] == 'E') {
9266 atts |= AM_E;
9267 if (debug_H & g_dbg_side) { printf(" E"); }
9268 } else if (bpe->sym[ip-1] == 'p') {
9269 atts |= AM_pi;
9270 if (debug_H & g_dbg_side) { printf(" p"); }
9271 } else if ((bpe->sym[ip-1] == 's')
9272 || (bpe->sym[ip-1] == 'q')) {
9273 atts |= AM_sq;
9274 if (debug_H & g_dbg_side) { printf(" sq"); }
9275 }
9276 if (debug_H & g_dbg_side) { printf("\n"); }
9277#else
9278 atts |= sym_attrs[bpe->sym[ip-1]].amkey;
9279 if (debug_H & g_dbg_side) {
9280 printf(" (%c)", bpe->sym[ip-1]);
9281 if (atts & AM_1) { printf(" 1"); }
9282 if (atts & AM_2) { printf(" 2"); }
9283 if (atts & AM_n) { printf(" n"); }
9284 if (atts & AM_r) { printf(" r"); }
9285 if (atts & AM_l) { printf(" l"); }
9286 if (atts & AM_E) { printf(" E"); }
9287 if (atts & AM_pi) { printf(" p"); }
9288 if (atts & AM_sq) { printf(" sq"); }
9289 if (atts & AM_plus) { printf(" +"); }
9290 if (atts & AM_mul) { printf(" *"); }
9291 if (atts & AM_pow) { printf(" ^"); }
9292 printf("\n");
9293 }
9294#endif
9295 }
9296
9297 /* ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' "
9298 Symbol-append loop
9299 Here we look at all the eligible symbols, and for each one we check the
9300 complexity limits to see if the symbol can be added to our partial
9301 expression.
9302 ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " ' " */
9303
9304 bpe->elen = (s16)(ip + 1);
9305 if (debug_I & g_dbg_side) { printf("%d symbols to try.\n", ns); }
9306 while (ns > 0) {
9307 s16 t_cpx; /* Test complexity with each candidate symbol */
9308
9309 /* get next symbol and see what this does to our complexity score */
9310 sym = *syms++;
9311 t_cpx = (s16)(in_cpx + sym_attrs[sym].sa_wgt);
9312 if (debug_I & g_dbg_side) {
9313 bpe->sym[ip] = 0;
9314 printf("trying [%s) . '%c' {%d}:\n", bpe->sym, sym, t_cpx);
9315 }
9316
9317 /* begin pruning */
9318 recurse = 1;
9319 if (0) {
9320
9321 /* Can the remaining symbols make a full expression that is
9322 within the global complexity limits? */
9323 } else if (t_cpx + rminw > e_maxw) {
9324 if (debug_J & g_dbg_side) {
9325 printf("prune complexity {%d} + rminw[%d] {%d} > e_maxw {%d}\n",
9326 t_cpx, ip+1, rminw, e_maxw);
9327 }
9328 recurse = 0;
9329 } else if (t_cpx + rmaxw < e_minw) {
9330 if (debug_J & g_dbg_side) {
9331 printf("prune complexity {%d} + rmaxw[%d] {%d} < e_minw {%d}\n",
9332 t_cpx, ip+1, rmaxw, e_minw);
9333 }
9334 recurse = 0;
9335
9336 /* does this symbol generate a stupid combination? */
9337 } else if (atts & sym_attrs[sym].sa_mask) {
9338 if (debug_K & g_dbg_side) {
9339 printf("prune on symbol rules: ");
9340 if (ip > 2) putchar(bpe->sym[ip-3]);
9341 if (ip > 1) putchar(bpe->sym[ip-2]);
9342 if (ip > 0) putchar(bpe->sym[ip-1]);
9343 printf(":%c atts %x & mask %x == %x reject\n", sym, atts,
9344 sym_attrs[sym].sa_mask, atts & sym_attrs[sym].sa_mask);
9345 }
9346 recurse = 0;
9347
9348 /* LHS expressions always start with 'x' */
9349 } else if (using_x && (ip == 0) && (sym != 'x')) {
9350 if (debug_K & g_dbg_side) {
9351 printf("prune LHS must start with 'x'\n");
9352 }
9353 recurse = 0;
9354
9355 /* Check symbol count for this symbol */
9356 } else if (sym_attrs[sym].sa_ct >= sym_attrs[sym].sa_alwd) {
9357 if (debug_L & g_dbg_side) {
9358 printf("prune symcount[%c]\n", sym);
9359 }
9360 recurse = 0;
9361 }
9362
9363 if (recurse) {
9364 /* we're going to use this symbol: write it into the BPE */
9365 bpe->sym[ip] = sym;
9366 sym_attrs[sym].sa_ct = (s16)(sym_attrs[sym].sa_ct + 1);
9367 /* update complexity */
9368 bpe->cplx = t_cpx;
9369
9370 /* okay, it's all set to recurse */
9371 n += ge_2(base, bpe, e_minw, e_maxw,
9372 ms, using_x); /* ge_2 self-recursive call */
9373
9374 /* undo the writing of this symbol. */
9375 sym_attrs[sym].sa_ct = (s16)(sym_attrs[sym].sa_ct - 1);
9376 } else {
9377 prune_count += 1.0;
9378 }
9379
9380 ns--;
9381 } /* End of "while (ns > 0)" */
9382
9383 /* undo the damage */
9384 bpe->elen = ip;
9385 bpe->cplx = in_cpx;
9386
9387 /* we're done with the IR's of this opcode */
9388 while(muc) { ms_undo(ms); muc--; }
9389
9390 return n;
9391} /* End of ge.2 */
9392
9393/* ge.1() takes a complete form like "aabacbc" and sets up the data
9394 structures needed by ge.2() to generate and execute all valid
9395 expressions (like [32s1+s*]) that fit that form. This includes a
9396 metastack, lists of complexity ranges, etc. */
9397stats_count ge_1(form *base, s16 e_minw, s16 e_maxw, s16 using_x,
9398 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw)
9399 /* %%% For proper solve-for-x with restricted symbol sets, the
9400 {a|b|c}_{min|max}w variables will have been generated from two sets of
9401 {a|b|c}_{min|max}w variables depending on whether we are generating an
9402 RHS or an LHS */
9403{
9404 pe bpe;
9405 metastack ms;
9406 s16 blen;
9407 stats_count n;
9408 s16 i, rminw, rmaxw;
9409 symbol sym;
9410 long start_ins_count;
9411
9412 blen = base->flen;
9413
9414 /* put a null at the end, used by the debug prints */
9415 (*base).sym[blen] = 0;
9416
9417 if (debug_t) {
9418 printf("ge_1 on form {%s}\n", (char *) (&((*base).sym[0])));
9419 printf("%3d >= %3d <= {%s} <= %3d >= %3d\n", e_maxw, base->min_weight,
9420 (char *) (&((*base).sym[0])), base->max_weight, e_minw);
9421 }
9422
9423 n = 0;
9424
9425 /* set up the pe struct */
9426 bpe.cplx = 0;
9427 bpe.elen = 0;
9428
9429 /* calculate and fill in the rmimw (remaining minimum weight) and
9430 rmaxw (remaining maximum weight) fields. For example, if the form
9431 is [abac] (length 4), the pe_rminw and pe_rmaxw arrays get set up
9432 like this:
9433 i 0 1 2 3 4
9434 symbol seft a b a c -
9435 pe_rminw[i] 31 21 14 4 0
9436 pe_rmaxw[i] 63 44 28 9 0
9437
9438 Each element of the array tells how much complexity might be added
9439 by the symbols at that position and later in the expression. For example,
9440 position 3 is seft c, and the minw and maxw values are 4 and 9. This
9441 is the symbol weight range for seft c (ranging from 4 points for [*]
9442 to 9 points for [L])
9443 %%% For proper solve-for-x with restricted symbol sets, the
9444 {a|b|c}_{min|max}w variables will have been generated from two sets of
9445 {a|b|c}_{min|max}w variables depending on whether we are generating an
9446 RHS or an LHS */
9447 if (debug_u) {
9448 printf("setting up rminw and rmaxw arrays for form [%s] (length %d):\n",
9449 (*base).sym, blen);
9450 }
9451 rminw = rmaxw = 0;
9452 i=blen;
9453 if (debug_u) {
9454 printf(" position %d (no sym): rminw[%d] = %d, rmaxw[%d] = %d.\n",
9455 i, i, rminw, i,rmaxw);
9456 }
9457 bpe.pe_rminw[i] = rminw;
9458 bpe.pe_rmaxw[i] = rmaxw;
9459 while(i>0) {
9460 i--;
9461 sym = (*base).sym[i];
9462 switch(sym) {
9463 case 'a':
9464 rminw = (s16)(rminw + a_minw);
9465 rmaxw = (s16)(rmaxw + a_maxw);
9466 break;
9467 case 'b':
9468 rminw = (s16)(rminw + b_minw);
9469 rmaxw = (s16)(rmaxw + b_maxw);
9470 break;
9471 case 'c':
9472 rminw = (s16)(rminw + c_minw);
9473 rmaxw = (s16)(rmaxw + c_maxw);
9474 break;
9475 }
9476 if (debug_u) {
9477 printf(" position %d, seft %c: rminw[%d] = %d, rmaxw[%d] = %d.\n",
9478 i, sym, i, rminw, i,rmaxw);
9479 }
9480 bpe.pe_rminw[i] = rminw;
9481 bpe.pe_rmaxw[i] = rmaxw;
9482 }
9483
9484 /* set up the metastack */
9485 ms_init(&ms);
9486
9487 /* generate! */
9488 start_ins_count = insert_count;
9489 n = ge_2(base, &bpe, e_minw, e_maxw, &ms, using_x); /* this is in ge_1 */
9490
9491 if(debug_v) {
9492 printf("form %s generated %ld expressions", base->sym, (long) n);
9493 if (insert_count > start_ins_count) {
9494 printf(" and inserted %ld", insert_count - start_ins_count);
9495 }
9496 printf(".\n");
9497 }
9498 return n;
9499}
9500
9501/* long g_dstats[MAX_ELEN]; */
9502
9503/* generate forms by simple recursive algorithm.
9504
9505 ------base------ ------next------
9506 flen sym-- stack flen sym-- stack Comments
9507 0 - 0 Initial call
9508 0 - 0 1 a 1 Setting up call to myself
9509 1 a 1 Entering recursive invocation
9510 1 a 1 2 aa 2 Setting up call to myself
9511 . . . (. . .)
9512 1 a 1 Entering recursive invocation
9513 1 a 1 2 ab 1 Setting up another call to myself
9514*/
9515stats_count gf_1(form *base, s16 e_minw, s16 e_maxw, s16 using_x,
9516 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw)
9517 /* %%% For proper solve-for-x with restricted symbol sets, the
9518 {a|b|c}_{min|max}w variables will have been generated from two sets of
9519 {a|b|c}_{min|max}w variables depending on whether we are generating an
9520 RHS or an LHS */
9521{
9522 s16 blen;
9523 form next;
9524 s16 i, recurse_forms, gen_expr;
9525 symbol s, slim;
9526 stats_count n;
9527
9528/* The "No identity optimization" skips the use of the 'I' operator and
9529 instead avoids using the 'b' seft in gf_1. */
9530#define NO_IDENTITY_OPTIMIZATION /* enable when brave */
9531
9532#ifdef NO_IDENTITY_OPTIMIZATION
9533 int sincr;
9534#endif
9535
9536 n = 0;
9537
9538 /* copy base form */
9539 blen = base->flen;
9540 for(i=0; i<blen; i++) {
9541 next.sym[i] = (*base).sym[i];
9542 next.stk[i] = (*base).stk[i];
9543 next.arg1[i] = (*base).arg1[i];
9544 }
9545 next.sym[i] = 0;
9546
9547 if (debug_w) {
9548 printf("gf_1 [%s)\n", next.sym);
9549 }
9550
9551 /* set up and generate forms elaborating by one symbol on the base */
9552 next.flen = (s16)(blen + 1);
9553 /* Find out if any seft-c symbols are enabled */
9554 if (n_csym == 0) {
9555 /* No: Use just 'a' and 'b' */
9556 slim = (symbol)'b';
9557 } else {
9558 /* Yes: Use all three sefts */
9559 slim = (symbol)'c';
9560 }
9561#ifdef NO_IDENTITY_OPTIMIZATION
9562 /* We have no seft-b symbols, not even the identity 'I', thus we can
9563 loop on just seft 'a' and 'c'. */
9564 sincr = 1;
9565 if (n_bsym == 0) {
9566 sincr = 2;
9567 }
9568 for ( s=((symbol)'a'); s <= slim; s=((symbol)(s+sincr)) ) {
9569#else
9570 for(s=((symbol)'a'); s <= slim; s++) {
9571#endif
9572 next.sym[blen] = s;
9573 if (debug_w) {
9574 next.sym[blen+1] = 0;
9575 }
9576 /* Stack changes by 1 for a, 0 for b, -1 for c */
9577 next.stack = (s16)(base->stack + (((symbol)'b') - s));
9578
9579 /* Compute the minimum and maximum possible weights, including the
9580 symbols we got from base plus the symbol we just added */
9581 if (s == 'a') {
9582 next.min_weight = (s16)(base->min_weight + a_minw);
9583 next.max_weight = (s16)(base->max_weight + a_maxw);
9584 } else if (s == 'b') {
9585 next.min_weight = (s16)(base->min_weight + b_minw);
9586 next.max_weight = (s16)(base->max_weight + b_maxw);
9587 } else {
9588 next.min_weight = (s16)(base->min_weight + c_minw);
9589 next.max_weight = (s16)(base->max_weight + c_maxw);
9590 }
9591
9592 /* check form symtax */
9593 recurse_forms = 1;
9594 if (next.stack < 1) {
9595 /* stack can't be zero or underflow */
9596 if (debug_w) {
9597 printf("gf_1 prune [%s) stack would underflow\n", next.sym);
9598 }
9599 recurse_forms = 0;
9600 } else if (next.min_weight + s_minw > e_maxw) {
9601 /* adding this symbol would make a form that can't possibly generate
9602 any expressions within the given complexity range. */
9603 if (debug_w) {
9604 printf("gf_1 prune [%s) complexity\n", next.sym);
9605 }
9606 recurse_forms = 0;
9607 } else if (blen > MAX_ELEN) {
9608 /* limits expression length to our physical allocation size. If this
9609 actually triggers at runtime, it implies that the weights are too
9610 spread out or that MAX_ELEN is just too darn small. */
9611 if (debug_w) {
9612 printf("gf_1 prune [%s) length\n", next.sym);
9613 }
9614 recurse_forms = 0;
9615 } else if ((next.flen + next.stack) > MAX_ELEN + 1) {
9616 /* in this case it would have no way of getting the stack down to one
9617 item before exceeding MAX_ELEN */
9618 if (debug_w) {
9619 printf("gf_1 prune [%s) stack too high\n", next.sym);
9620 }
9621 recurse_forms = 0;
9622 }
9623
9624 /* Fill in the stack-height and arg1 arrays. Here are some examples:
9625 expr xsE1Exs^- xsEexs^- 34+
9626 ix 012345678 01234567 012
9627 form abbababcc abbaabcc aac
9628 stk 111223321 11123321 121
9629 arg1 .......42 ......32 ..0
9630 */
9631 next.stk[blen] = next.stack;
9632 next.arg1[blen] = ARG1_NA; /* Default value is "not applicable" */
9633 if (s == ((symbol)'c')) {
9634 /* Find where the first argument is */
9635 for (i=(s16)(blen-2); i>=0; i--) {
9636 if (next.stk[i] == next.stack) {
9637 next.arg1[blen] = i;
9638 i = -1; /* we found it, make the loop exit */
9639 }
9640 }
9641 }
9642
9643 /* check viability for expressions */
9644 gen_expr = 0;
9645 if (next.stack == 1) {
9646 gen_expr = 1;
9647 /* if (next.flen < MAX_ELEN) { g_dstats[next.flen]++; } */
9648 if (next.min_weight > e_maxw) {
9649 if (debug_w) {
9650 printf("gf_1 [%s] min weight too big for expressions\n", next.sym);
9651 }
9652 gen_expr = 0;
9653 } else if (next.max_weight < e_minw) {
9654 if (debug_w) {
9655 printf("gf_1 [%s] max weight too small for expressions\n", next.sym);
9656 }
9657 gen_expr = 0;
9658 }
9659 }
9660
9661 if (gen_expr) {
9662 if (debug_w) {
9663 printf("gf_1 generating expressions on form [%s]\n", next.sym);
9664 }
9665
9666 g_ne += ge_1(&next, e_minw, e_maxw, using_x,
9667 a_minw, a_maxw, b_minw, b_maxw, c_minw, c_maxw); /* this is in gf_1 */
9668 }
9669
9670 /* recurse, if appropriate */
9671 if (recurse_forms) {
9672 n += gf_1(&next, e_minw, e_maxw, using_x,
9673 a_minw, a_maxw, b_minw, b_maxw, c_minw, c_maxw); /* gf_1 self-recursive */
9674 }
9675
9676 /* count the leaf nodes... leaf. huh-huh. heh huh heh-heh. */
9677 if (gen_expr) {
9678 n++;
9679 }
9680 }
9681
9682 return(n);
9683} /* End of gf.1 */
9684
9685/* generate forms on-the-fly, given a minimum and maxmum complexity score.
9686 * It will generate all expressions with valid forms that lie within the
9687 * complexity limits. */
9688stats_count gen_forms(s16 e_minw, s16 e_maxw, s16 using_x,
9689 s16 a_minw, s16 a_maxw, s16 b_minw, s16 b_maxw, s16 c_minw, s16 c_maxw)
9690 /* %%% For proper solve-for-x with restricted symbol sets, the
9691 {a|b|c}_{min|max}w variables will have been generated from two sets of
9692 {a|b|c}_{min|max}w variables depending on whether we are generating an
9693 RHS or an LHS */
9694{
9695 form base;
9696 stats_count n;
9697/* int i; for(i=0; i<MAX_ELEN; i++) { g_dstats[i] = 0; } */
9698
9699 n = 0;
9700 base.flen = 0;
9701 base.stack = 0;
9702 base.min_weight = 0;
9703 base.max_weight = 0;
9704 n = gf_1(&base, e_minw, e_maxw, using_x,
9705 a_minw, a_maxw, b_minw, b_maxw, c_minw, c_maxw);
9706
9707/* if (debug_y) {
9708 printf("%s", "nforms[i] >= {");
9709 for(i=0; i<MAX_ELEN; i++) {
9710 if (i > 0) { printf(", "); }
9711 printf("%ld", g_dstats[i]);
9712 }
9713 printf(", ...}\n");
9714 } */
9715
9716 return(n);
9717} /* End of gen.forms */
9718
9719/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9720 Routines for initializing the data structures and variables used for the
9721 search.
9722*/
9723
9724/* The amkey is a bitmask of all the single-symbol pattern flag bits
9725 * for a symbol. For example, the symbol 'n' has a single bit, AM_n. This
9726 * is all just a lookup-table optimization for ge.2(), which would
9727 * otherwise have to compare the current symbol against all the
9728 * single-symbol flags. */
9729void def_amkey(const char * syms, attr_bits mask)
9730{
9731 symbol * s = (symbol *) syms;
9732 while(*s) {
9733 sym_attrs[*s].amkey |= mask;
9734 s++;
9735 }
9736}
9737
9738void define_amkeys(void)
9739{
9740 def_amkey("1", AM_1);
9741 def_amkey("2", AM_2);
9742 def_amkey("n", AM_n);
9743 def_amkey("r", AM_r);
9744 def_amkey("sq", AM_sq);
9745 def_amkey("l", AM_l);
9746 def_amkey("E", AM_E);
9747 def_amkey("p", AM_pi);
9748 def_amkey("+", AM_plus);
9749 def_amkey("*", AM_mul);
9750 def_amkey("^", AM_pow);
9751}
9752
9753void add_symbol(symbol sym, const char * name_forth, const char * name_infix,
9754 symbol seft, s16 weight,
9755 const char * def_terse, const char * def_normal, const char * description)
9756{
9757 if (out_expr_format == OF_NORMAL) {
9758 sym_attrs[sym].defn = def_normal;
9759 } else {
9760 sym_attrs[sym].defn = def_terse;
9761 }
9762 if (sym_attrs[sym].defn) {
9763 if(strlen(sym_attrs[sym].defn) > LINELEFT_INIT) {
9764 printf("Symbol definition for '%c' too long:\n%s\n", sym,
9765 sym_attrs[sym].defn);
9766 }
9767 }
9768 sym_attrs[sym].desc = description;
9769
9770 /* Only set the names if the user didn't assign a non-null name */
9771 if ((sym_attrs[sym].sa_name==0) || (strlen(sym_attrs[sym].sa_name) == 0)) {
9772 if (name_infix) {
9773 sym_attrs[sym].sa_name = name_infix;
9774 }
9775 if (name_forth) {
9776 sym_attrs[sym].name_forth = name_forth;
9777 }
9778 }
9779
9780 sym_attrs[sym].seft = seft;
9781
9782 if (IS_PHANTOM(sym)) {
9783 return;
9784 }
9785
9786 /* All symbols have a base complexity of 10 points, plus the individual
9787 per-symbol weight */
9788 if (sym_attrs[sym].preempt_weight >= 0) {
9789 weight = sym_attrs[sym].preempt_weight;
9790 } else {
9791 weight = (s16)(weight + weight_base);
9792 }
9793
9794 sym_attrs[sym].sa_wgt = weight;
9795 sym_attrs[sym].sa_mask = 0;
9796
9797 if (sym_attrs[sym].sa_alwd == 0) {
9798 return;
9799 }
9800
9801 /* Set the sa_known flag to keep track of which symbols made it this far;
9802 this is for use by setup_abc_mmw(). */
9803 g_addsym_seq++;
9804 sym_attrs[sym].sa_known = g_addsym_seq;
9805 /* printf("add_symbol: '%c'\n", (char) sym); */
9806
9807 if (seft == 'a') {
9808 if (n_asym >= MAX_SEFT_POP) {
9809 printf("add_symbol: Too many seft 'a' symbols.\n");
9810 print_end(-1);
9811 }
9812 g_asym[n_asym++] = sym;
9813 } else if (seft == 'b') {
9814 if (n_bsym >= MAX_SEFT_POP) {
9815 printf("add_symbol: Too many seft 'b' symbols.\n");
9816 print_end(-1);
9817 }
9818 g_bsym[n_bsym++] = sym;
9819 } else if (seft == 'c') {
9820 if (n_csym >= MAX_SEFT_POP) {
9821 printf("add_symbol: Too many seft 'c' symbols.\n");
9822 print_end(-1);
9823 }
9824 g_csym[n_csym++] = sym;
9825 }
9826} /* End of add.symbol */
9827
9828/* Calculate, or re-calculate, the global g_{a|b|c}_{min|max}w
9829variables and s_minw. This is needed for proper solve-for-x with restricted
9830symbol sets. */
9831void setup_abc_mmw(void)
9832{
9833 int i;
9834 symbol seft;
9835 s16 weight;
9836
9837 /* %%% For proper solve-for-x with restricted symbol sets, we'll probably
9838 need to recalculate the number of symbols in n_{a|b|c}sym and rebuild the
9839 g_{a|b|c}sym arrays. If needed, I can preserve the order of the arrays
9840 (which affects the order symbols are tried in ge_2) by using the
9841 g_addsym_seq values in sa_known. */
9842 g_a_minw = g_b_minw = g_c_minw = (int) MAX_SYMBOL_WEIGHT;
9843 g_a_maxw = g_b_maxw = g_c_maxw = (int) MIN_SYMBOL_WEIGHT;
9844
9845 for (i=0; i<SYMBOL_RANGE; i++) {
9846 if (sym_attrs[i].sa_known) {
9847 /* This symbol was enabled at init.2() time */
9848 if (sym_attrs[i].sa_alwd) {
9849 /* We want this symbol for this petit cycle. %%% For proper solve-for-x
9850 with restricted symbol sets, this part of the test will
9851 depend on whether we're about to generate LHS or RHS */
9852
9853 seft = sym_attrs[i].seft;
9854 weight = sym_attrs[i].sa_wgt;
9855
9856 if (seft == 'a') {
9857 if (weight < g_a_minw) { g_a_minw = weight; }
9858 if (weight > g_a_maxw) { g_a_maxw = weight; }
9859 } else if (seft == 'b') {
9860 if (weight < g_b_minw) { g_b_minw = weight; }
9861 if (weight > g_b_maxw) { g_b_maxw = weight; }
9862 } else if (seft == 'c') {
9863 if (weight < g_c_minw) { g_c_minw = weight; }
9864 if (weight > g_c_maxw) { g_c_maxw = weight; }
9865 }
9866 } } }
9867
9868 s_minw = g_a_minw;
9869 if (g_b_minw < s_minw) {
9870 s_minw = g_b_minw;
9871 }
9872 if (g_c_minw < s_minw) {
9873 s_minw = g_c_minw;
9874 }
9875} /* End of setup.abc_mmw */
9876
9877const char * seft_names[3] = {
9878 "Explicit values",
9879 "Functions of one argument",
9880 "Functions of two arguments",
9881};
9882
9883/* Show the set of symbols that is defined, along with seft, weight,
9884 definition, etc. */
9885void show_symset(void)
9886{
9887 int i, seft;
9888 const char * def;
9889
9890 for(seft = 'a'; seft <= 'c'; seft++) {
9891 printf("%s:\n", seft_names[seft-'a']);
9892 printf(" sym seft wght name description\n");
9893 for (i=0; i<SYMBOL_RANGE; i++) {
9894 if (!(IS_PHANTOM(i)) && (sym_attrs[i].seft == seft) && (sym_attrs[i].sa_alwd)) {
9895 printf(" %c %c %2d %-4s", i, sym_attrs[i].seft,
9896 sym_attrs[i].sa_wgt, sym_attrs[i].sa_name);
9897 def = sym_attrs[i].defn;
9898 if (def == 0) {
9899 def = sym_attrs[i].desc;
9900 }
9901 if (def) {
9902 printf(" %s", def);
9903 }
9904 printf("\n");
9905 }
9906 }
9907 printf("\n");
9908 }
9909} /* End of show.symset */
9910
9911/* add.rule compares a pruning rule's attributes to the list of valid
9912symbols; if the rule matches (i.e. if the set of permitted symbols
9913include the necessary substitute symbols), the rule's trigger-bitmask
9914gets added to the bitmask for the symbol that this rule blocks.
9915
9916For example, executing the rule ("-", '+', AM_n) blocks the '+' symbol
9917and is triggered by the bitmask AM_n. If this rule is enabled, '+'
9918will never get appended to any partial expression ending in 'n'. This
9919is because the sequence [n+] is equivalent to [-]. Therefore, this
9920rule can only be used if the permitted symbols include '-'. So this
9921function adds the bit AM_n to the rule bitmask for '+' only if the
9922sym_allowed list contains '-'.
9923
9924The parameters are:
9925
9926 ss Substitute symbols
9927 sy Symbol to prohibit
9928 mask Flag bits that trigger the rule
9929*/
9930void add_rule(const char * ss, char sy, attr_bits mask)
9931{
9932 symbol * symset = (symbol *) ss;
9933 symbol sym = (symbol) sy;
9934 symbol sreq;
9935 s16 allowed;
9936 symbol * s; /* Copy of 'symset' for loop */
9937
9938 /* The rule is allowed unless one or more in its symbolset are restricted
9939 in number by our symbol frequency options. */
9940
9941 /* %%% solve-for-x: The ss (substitute symbols) need to be compared
9942 against the INTERSECTION of the LHS and RHS symbol sets */
9943 allowed = 1;
9944 s = symset;
9945 while((sreq = *s++)) {
9946 if (sym_attrs[sreq].sa_alwd < MAX_ELEN) {
9947 allowed = 0;
9948 }
9949 }
9950 if (allowed) {
9951 if (debug_x) {
9952 printf("Using rule %8s %c %4x\n", symset, sym, mask);
9953 }
9954
9955 /* */
9956 sym_attrs[sym].sa_mask |= mask;
9957 }
9958} /* End of add.rule */
9959
9960/* Initialize numerics (values of constants)
9961 For initialization of printf format strings, see init_formats */
9962void init_numerics(void)
9963{
9964 if (debug_z) {
9965 printf("init_num: nominal %d digits, usable %d\n",
9966 k_nominal_digits, k_usable_digits);
9967 }
9968
9969 {
9970#ifdef REDUNDANT_ULP_INIT
9971 /* Figure out the size of the ULP (unit in least position), used to
9972 auto-compute some of the constants used for precision, rounding,
9973 overflow, and tautology handling. */
9974 ries_val k14 = 181.0 / 128.0; /* Approximately sqrt(2) */
9975 ries_val ulp = 1.0; /* Unit in the Last Place */
9976 ries_val sum = k14 + ulp;
9977 while (sum != k14) {
9978 ulp = ulp / 2.0;
9979 sum = k14 + ulp;
9980 }
9981 k_precision_ulp = (ries_dif) ulp;
9982#endif
9983 k_precision_ulp = 2.0 * k_ulp;
9984 /* Before 20120102, RIES was setting k_min_best.match to 1.0e-15,
9985 which is 9.0072 times the ULP of IEEE binary64. */
9986 k_min_best_match = 9.0072 * (ries_dif) k_precision_ulp;
9987 if (debug_z) {
9988 printf("init_num: ulps are %g, %g ; kmbm=%g\n",
9989 k_precision_ulp, k_ulp, k_min_best_match);
9990 }
9991 }
9992
9993
9994 /* Initialize the transcendental constants */
9995
9996 {
9997 ries_val check_phi
9998 = (ries_val) 1.61803398874989484820458683436563811772030L;
9999
10000 k_phi = (SQRT(5.0) + 1.0) / 2.0;
10001 if (debug_z) {
10002 printf("init_num: k_phi ");
10003 spfg(k_nominal_digits, k_phi);
10004 printf(" chk ");
10005 spfg(k_nominal_digits, check_phi);
10006 printf(" diff %g\n", dbl(check_phi - k_phi));
10007 }
10008 }
10009
10010 {
10011 ries_val check_e
10012 = (ries_val) 2.71828182845904523536028747135266249775724L;
10013 ries_val i;
10014 /* This is just the Taylor series for e^1:
10015
10016 e = SIGMA_(k=0..inf) [ 1 / k! ]
10017 = 1 + 1 + 1/2 + 1/3*2 + 1/4*3*2 + 1/5+4+3+2 + ...
10018 = 1 + 1/1 * (1 + 1/2 * (1 + 1/3 * (1 + 1/4 * (1 + ...))))
10019 = 1 + (1 + (1 + (1 + (1 + ... )/4 )/3 )/2 )/1
10020
10021 which can be readily unrolled into the loop shown here.
10022 */
10023 i = 31.0; /* 19 for IEEE binary64; 23 For 64-bit mantissa;
10024 31 for PowerPC long double */
10025 k_e = 1.0 / i;
10026 while(i > 1.0) {
10027 i -= 1.0;
10028 /* 1.0 + 1/i * (k_e) */
10029 k_e = 1.0 + k_e / i;
10030 }
10031 if (debug_z) {
10032 printf("init_num: k_e ");
10033 spfg(k_nominal_digits, k_e);
10034 printf(" chk ");
10035 spfg(k_nominal_digits, check_e);
10036 printf(" diff %g\n", dbl(check_e - k_e));
10037 }
10038 }
10039
10040 {
10041 ries_val check_pi
10042 = (ries_val) 3.14159265358979323846264338327950288419716L;
10043 ries_val i;
10044
10045 /* This pi algorithm is based on the infinite sum attributed to
10046 Isaac Newton:
10047
10048 pi/2 = SIGMA_(k=0..inf) [ k! / (2k+1)!! ]
10049 = 1 + 1/3 + 2/5*3 + 3*2/7*5*3 + 4*3*2/9*7*5*3 + ...
10050 = 1 + 1/3 * (1 + 2/5 * (1 + 3/7 * (1 + 4/9 * (1 + ...))))
10051
10052 which can be readily unrolled into the loop shown here. It is slow
10053 (requiring lots of divisions by distinct primes) but surpasses
10054 faster-converging methods like Gauss-Legendre and Borwein-Borwein
10055 in that it produces the most precise possible answer in IEEE binary64.
10056 */
10057 i = 103.0; /* 50 for IEEE binary64; 61 for long double;
10058 103 for PowerPC long double */
10059 k_pi = 1.57;
10060 while(i > 1.0) {
10061 i -= 1.0;
10062 k_pi = 1.0 + (i / (1.0 + (2.0 * i))) * k_pi;
10063 }
10064 k_pi = 2.0 * k_pi;
10065 if (debug_z) {
10066 printf("init_num: k_pi ");
10067 spfg(k_nominal_digits, k_pi);
10068 printf(" chk ");
10069 spfg(k_nominal_digits, check_pi);
10070 printf(" diff %g\n", dbl(check_pi - k_pi));
10071 }
10072
10073 /* If the trig scale hasn't been set, use the default value */
10074 if (k_sincos_arg_scale <= 0) {
10075 k_sincos_arg_scale = k_pi;
10076 g_trig_scale_default = B_TRUE;
10077 }
10078
10079 k_2pi = 2.0 * k_pi;
10080 }
10081} /* End of init.numerics */
10082
10083/* init_symbol_names does nothing now, but will be needed when
10084/ user-defined functions and constants are implemented. The symbol names
10085/ table is updated as we parse through the arguments, and once defined,
10086/ a symbol name can be used by another function definition. This routine
10087/ will set up this database in a suitable initial state. */
10088void init_symbol_names(void)
10089{
10090 int i;
10091
10092 for(i=0; i<SYMBOL_RANGE; i++) {
10093 sym_attrs[i].sa_name = "";
10094 sym_attrs[i].name_forth = 0;
10095 }
10096}
10097
10098void allsyms_set(s16 n, int include_x)
10099{
10100 int i;
10101
10102 for(i=0; i<SYMBOL_RANGE; i++) {
10103 if (include_x || ((char) i != 'x')) {
10104 sym_attrs[i].sa_alwd = n;
10105 }
10106 }
10107}
10108
10109void somesyms_set(symbol * s, s16 n)
10110{
10111 while (s && *s) {
10112 sym_attrs[*s].sa_alwd = n;
10113 /* if (*s == 'W') { printf("Set W to %d\n", n); } */
10114 s++;
10115 }
10116}
10117
10118void set_anagram(char * anagram)
10119{
10120 int i;
10121
10122 if (anagram) {
10123 const char * ana_syms = "123456789efprs";
10124 symbol s;
10125 /* --numeric.anagram option specifies a set of digits which can be used
10126 (in any order) in the RHS. They can give zeros or other symbols
10127 if they want, but we only pay attention to the digits 1-9, constants
10128 efp, and 'r' and 's' which represent a '1' or '2' respectively. */
10129 for(i=0; ana_syms[i]; i++) {
10130 s = (symbol)(ana_syms[i]);
10131 sym_attrs[s].sa_alwd = 0;
10132 }
10133 for(i=0; anagram[i]; i++) {
10134 s = (symbol)(anagram[i]);
10135 if (strchr(ana_syms, ((char) s))) {
10136 sym_attrs[s].sa_alwd++;
10137 }
10138 }
10139 }
10140} /* End of set.anagram */
10141
10142/* init1() sets defaults (anything that can be overridden or changed by
10143 command-line arguments) */
10144void init1()
10145{
10146 s16 i;
10147
10148 inittime();
10149 init_mem();
10150
10151 g_enable_output = 1;
10152
10153 for(i=0; i<MAX_FIND_EXPR; i++) {
10154 g_find_expr[i] = 0;
10155 }
10156 g_num_find_expr = 0;
10157 g_eval_expr = 0;
10158
10159 /* There are four command-line options for specifying the symbolset:
10160 -S, -O, -E, and -N. -S means "use only these symbols"; -O means "use
10161 at most one of these per expression"; -E and -N enable and disable
10162 certain symbols without affecting any others.
10163
10164 Initially all symbols are enabled except 'W'. While scanning the
10165 command-line, when any of these symbolset-selection arguments is
10166 encountered they cause the sa.alwd fields (FKA an array "sym_allowed")
10167 to be modified. sa.alwd speficies how many of each symbol is
10168 allowed in each expression. -N changes the sa.alwd value to 0,
10169 -O sets it to 1, -E and -S set it to MAX_ELEN, and -S also sets all
10170 other symbols' sa.alwd value to 0.
10171
10172 These are done in the order the options are given. (In earlier versions of
10173 RIES, there were only the options -S, -N and -O; their parameters
10174 were remembered until all command-line options were parsed, and then
10175 they were handled as if they had been given in the order: -N, then
10176 -O, then -S).
10177 */
10178 for(i=0; i<SYMBOL_RANGE; i++) {
10179 sym_attrs[i].preempt_weight = -1;
10180 }
10181 allsyms_set(MAX_ELEN, 1);
10182 somesyms_set((symbol *) "W", 0);
10183 S_option = B_FALSE;
10184 NOS_options = B_FALSE;
10185 g_show_ss = B_FALSE;
10186 x_lhs_only = B_FALSE;
10187 g_no_cv_simplify = B_FALSE;
10188 g_one_sided = B_FALSE;
10189 g_solve_for_x = B_FALSE;
10190 g_reported_exhaustion = B_FALSE;
10191 g_refinement = B_TRUE;
10192 g_max_matches = DEFAULT_MAX_MATCHES;
10193
10194 /* Set default serach level */
10195 g_levadj = DEFAULT_LEV_ADJ;
10196 tlevel = DEFAULT_LEV_BASE + g_levadj;
10197
10198 g_restrict_subexpr = TYPE_NONE;
10199 g_restrict_exponents = TYPE_NONE;
10200 g_restrict_trig_args = TYPE_NONE;
10201 g_relative_x = B_TRUE;
10202 g_wide_output = B_FALSE;
10203 g_explicit_multiply = B_FALSE;
10204 out_expr_format = OF_NORMAL;
10205 init_symbol_names();
10206
10207 /* 20120105: without cv.simplify, canon reduction is a bit of a nuisance,
10208 / so it is disabled by default right now.
10209 / In the future we might set it back to:
10210 / CANONVAL_NEGATE | CANONVAL_RECIPROCAL | CANONVAL_DIV2 | CANONVAL_MUL2 */
10211 g_canon_ops = 0;
10212
10213 debug_m = 0; debug_M = 0; debug_n = 0; debug_N = 0; debug_o = 0; debug_p = 0;
10214 debug_Q = 0; debug_q = 0; debug_r = 0; debug_S = 0; debug_s = 0; debug_t = 0;
10215 debug_u = 0; debug_v = 0; debug_w = 0; debug_x = 0; debug_y = 0;
10216 debug_A = 0; debug_B = 0; debug_C = 0; debug_D = 0; debug_E = 0;
10217 debug_F = 0; debug_G = 0; debug_H = 0; debug_I = 0; debug_J = 0;
10218 debug_K = 0; debug_L = 0; debug_z = 0; debug_0 = 0;
10219
10220 g_allow_slow_message = 1;
10221
10222 g_min_memory = 0;
10223 g_max_memory = 1.0e20;
10224
10225 g_target = 1.0;
10226} /* End of init1 */
10227
10228/* Post-arguments initialization: All the command-line arguments have been
10229 detected; now we proceed to initialize globals that depend on arguments */
10230void init2()
10231{
10232 s16 i;
10233
10234 if (debug_z) {
10235 printf("Struct sizes:\n");
10236 printf(" ALLOC_SIZE == %ld\n", ((long) ALLOC_SIZE));
10237 printf(" MAX_ELEN == %d, TS_ALLOC_L == %d, TS_ALLOC_R == %d\n",
10238 ((int) MAX_ELEN), ((int) TS_ALLOC_L), ((int) TS_ALLOC_R));
10239 printf(" sizeof(sym_attr_block) == %d\n", (int) sizeof(sym_attr_block));
10240 printf(" sizeof(form) == %d\n", (int) sizeof(form));
10241 printf(" sizeof(pe) == %d\n", (int) sizeof(pe));
10242 printf(" sizeof(metastack) == %d\n", (int) sizeof(metastack));
10243 printf(" sizeof(expr) == %d\n", (int) sizeof(expr));
10244 }
10245
10246 init_numerics();
10247
10248 max_flen = 0;
10249 lhs_root = 0;
10250
10251 /* Prohibit -Nx (act as if -Sx was given unless they specified -Ox) */
10252 if (sym_attrs['x'].sa_alwd == 1) {
10253 x_lhs_only = B_TRUE;
10254 } else {
10255 sym_attrs['x'].sa_alwd = MAX_ELEN;
10256 }
10257
10258#ifdef DUMMY_LAMBERT
10259 if (sym_attrs['W'].sa_alwd) {
10260 printf("%s: The Lambert W function 'W' requires the stand-alone maths library.\n",
10261 g_argv0);
10262 brief_help();
10263 print_end(1);
10264 }
10265#endif
10266
10267 for(i=0; i<SYMBOL_RANGE; i++) {
10268 sym_attrs[i].seft = 0;
10269 sym_attrs[i].defn = 0;
10270 sym_attrs[i].desc = 0;
10271 sym_attrs[i].def_given = 0;
10272 sym_attrs[i].def_needed = 0;
10273 sym_attrs[i].amkey = 0;
10274 sym_attrs[i].sa_known = 0;
10275 }
10276 used_trig = 0;
10277 n_asym = n_bsym = n_csym = 0;
10278 g_used_identity = B_FALSE;
10279 weight_base = 10;
10280 g_addsym_seq = 0;
10281
10282 /* Now we fill in the table with all the specific values for the symbols
10283 we actually know about. %%% This will include custom constants from the
10284 queue built up during argument scanning. */
10285
10286 add_symbol(ADDSYM_NAMES(' ', 0, "NOP"),
10287 '0', 0, 0, 0, "no operation");
10288
10289 /* seft 'a' symbols are constants.
10290 For most of these, the weight is close to 10.0*ln(x)/ln(10) */
10291 add_symbol(ADDSYM_NAMES('1', 0, "1"),
10292 'a', 0, 0, 0, "integer");
10293 add_symbol(ADDSYM_NAMES('f', "phi", "phi"),
10294 'a', 8, "f = phi, the golden ratio, (1+sqrt(5))/2",
10295 "phi = the golden ratio, (1+sqrt(5))/2", "");
10296 add_symbol(ADDSYM_NAMES('2', 0, "2"),
10297 'a', 3, 0, 0, "integer");
10298 add_symbol(ADDSYM_NAMES('e', "e", "e"),
10299 'a', 6, "e = base of natural logarithms, 2.71828...",
10300 "e = base of natural logarithms, 2.71828...", "");
10301 add_symbol(ADDSYM_NAMES('3', 0, "3"),
10302 'a', 5, 0, 0, "integer");
10303 add_symbol(ADDSYM_NAMES('p', "pi", "pi"),
10304 'a', 4, "p = pi, 3.14159...", "pi = 3.14159...", "");
10305 add_symbol(ADDSYM_NAMES('4', 0, "4"),
10306 'a', 6, 0, 0, "integer");
10307 add_symbol(ADDSYM_NAMES('5', 0, "5"),
10308 'a', 7, 0, 0, "integer");
10309 add_symbol(ADDSYM_NAMES('6', 0, "6"),
10310 'a', 8, 0, 0, "integer");
10311 add_symbol(ADDSYM_NAMES('7', 0, "7"),
10312 'a', 8, 0, 0, "integer");
10313 add_symbol(ADDSYM_NAMES('8', 0, "8"),
10314 'a', 9, 0, 0, "integer");
10315 add_symbol(ADDSYM_NAMES('9', 0, "9"),
10316 'a', 9, 0, 0, "integer");
10317 add_symbol(ADDSYM_NAMES('x', 0, "x"),
10318 'a', 5, 0, 0, "the variable of the equation");
10319
10320 /* seft 'b' symbols */
10321 add_symbol(ADDSYM_NAMES('n', "neg", "-"),
10322 'b', -3, "n = negative", 0, "negate");
10323 add_symbol(ADDSYM_NAMES('r', "recip","1/"),
10324 'b', -3, 0, 0, "reciprocal");
10325 add_symbol(ADDSYM_NAMES('s', "dup*", "^2"),
10326 'b', -1, 0, 0, "square");
10327 add_symbol(ADDSYM_NAMES('q', "sqrt", "sqrt"),
10328 'b', -1, "q = square root", "sqrt(x) = square root", "");
10329 add_symbol(ADDSYM_NAMES('l', "ln", "ln"),
10330 'b', 3, "l = ln, natural logarithm or log base e",
10331 "ln(x) = natural logarithm or log base e", "");
10332 add_symbol(ADDSYM_NAMES('E', "exp", "e^"),
10333 'b', 3, 0, 0, "natural exponent function");
10334
10335 if (k_sincos_arg_scale == k_pi) {
10336 /* With a scale factor of pi we'll call the functions "sinpi", etc. */
10337 add_symbol(ADDSYM_NAMES('S', "sinpi", "sinpi"),
10338 'b', 3, "S(x) = sinpi(x) = sin(pi * x)",
10339 "sinpi(X) = sin(pi * x)", "sinpi");
10340 add_symbol(ADDSYM_NAMES('C', "cospi", "cospi"),
10341 'b', 3, "C(x) = cospi(x) = cos(pi * x)",
10342 "cospi(X) = cos(pi * x)", "cospi");
10343 add_symbol(ADDSYM_NAMES('T', "tanpi", "tanpi"),
10344 'b', 6, "T(x) = tanpi(x) = tan(pi * x)",
10345 "tanpi(X) = tan(pi * x)", "tanpi");
10346 } else {
10347 /* With any other scale factor we just call it "sin", etc. and let
10348 the user fend for himself (there are too many possibilities to
10349 test for: degrees, grads, and of course natural units, plus all
10350 the nonstandard units). Presumably if the user gave a scale factor,
10351 she knows what the definition is. */
10352 add_symbol(ADDSYM_NAMES('S', "sin", "sin"),
10353 'b', 3, "S(x) = sine", 0, "sine");
10354 add_symbol(ADDSYM_NAMES('C', "cos", "cos"),
10355 'b', 3, "C(x) = cosine", 0, "cosine");
10356 add_symbol(ADDSYM_NAMES('T', "tan", "tan"),
10357 'b', 6, "T(x) = tangent", 0, "tangent");
10358 }
10359
10360 add_symbol(ADDSYM_NAMES('W', "W", "W"),
10361 'b', 5, "W(x) = LambertW(x) = inverse(x=w*e^w)",
10362 "W(x) = LambertW(x) = inverse(x=w*e^w)", "W");
10363
10364
10365 /* seft 'c' symbols */
10366 add_symbol(ADDSYM_NAMES('+', "+", "+"),
10367 'c', -6, 0, 0, "add");
10368 add_symbol(ADDSYM_NAMES('-', "-", "-"),
10369 'c', -5, 0, 0, "subtract");
10370 add_symbol(ADDSYM_NAMES('*', "*", "*"),
10371 'c', -6, 0, 0, "multiply");
10372 add_symbol(ADDSYM_NAMES('/', "/", "/"),
10373 'c', -5, 0, 0, "divide");
10374 add_symbol(ADDSYM_NAMES('^', "**", "^"),
10375 'c', -4, 0, 0, "A ^ B = A to the power of B");
10376 add_symbol(ADDSYM_NAMES('v', "root", "\"/"),
10377 'c', -3, "A v B = Ath root of B", "A\"/B = Ath root of B", ""); /* Power[B, Rational[1, A]] */
10378 add_symbol(ADDSYM_NAMES('L', "logN", "log_"),
10379 'c', -1, "A L B = logarithm to base A of B = ln(B) / ln(A)",
10380 "log_A(B) = logarithm to base A of B = ln(B) / ln(A)", ""); /* Log_x(y) */
10381#if 0
10382 add_symbol(ADDSYM_NAMES('A', "atan2", "arctan2"),
10383 'c', -4, "x A y = arctangent of x/y",
10384 "arctan(x,y) = arctangent of x/y", "");
10385#endif
10386
10387 /* phantom symbols -- used only for postfix to infix translation */
10388 add_symbol(ADDSYM_NAMES(PS_REVDIV, 0, "!/"),
10389 'c', 0, 0, 0, 0);
10390 add_symbol(ADDSYM_NAMES(PS_REVSUB, 0, "!-"),
10391 'c', 0, 0, 0, 0);
10392 add_symbol(ADDSYM_NAMES(PS_cross, 0, "><"),
10393 'c', 0, 0, 0, 0);
10394 add_symbol(ADDSYM_NAMES(PS_REVPOW, 0, "!^"),
10395 'c', 0, 0, 0, 0);
10396
10397 /* These are used for infix formatting */
10398 /* sym_attrs['('].sa_name = "("; sym_attrs[')'].sa_name = ")"; */
10399 add_symbol(ADDSYM_NAMES('(', 0, "("), 0, 0, 0, 0, 0);
10400 add_symbol(ADDSYM_NAMES(')', 0, ")"), 0, 0, 0, 0, 0);
10401 add_symbol(ADDSYM_NAMES('=', 0, "="), 0, 0, 0, 0, 0);
10402
10403 /* This symbol is a temporary placeholder for infix multiplication.
10404 %%% Figure out if I need this at all, or use PS_cross instead */
10405 sym_attrs['.'].sa_name = " ";
10406
10407 /* Report error and abort if there is only one type A symbol
10408 (namely X, which is always included) */
10409 if (n_asym < 2) {
10410 printf("%s: You must allow at least one constant symbol.\n",
10411 g_argv0);
10412 if (S_option) {
10413 printf(" (Note that the -S option disables all other symbols)\n");
10414 }
10415 brief_help();
10416 print_end(1);
10417 }
10418
10419 if (n_bsym == 0) {
10420 if (n_csym == 0) {
10421 printf("%s: You must allow at least one operator symbol.\n",
10422 g_argv0);
10423 brief_help();
10424 print_end(1);
10425 }
10426#ifdef NO_IDENTITY_OPTIMIZATION
10427 /* With the "no identity" optimization we don't need this kludge. */
10428#else
10429 /* Add "identity" operator if there are no type B symbols */
10430 sym_attrs['I'].sa_alwd = MAX_ELEN;
10431 add_symbol(ADDSYM_NAMES('I', "nop", "I"),
10432 'b', 10, "I = identity", 0, "identity");
10433 g_used_identity = B_TRUE;
10434#endif
10435 }
10436
10437 /* Setup the g_{a|b|c}_{min|max}w variables */
10438 setup_abc_mmw();
10439
10440 /* If there are no type C symbols, gf_1 will notice n_csym and
10441 will skip generating forms with 'c's */
10442
10443 define_amkeys();
10444
10445 /* operators have masks for pruning (optimization). These are commented
10446 * with reasons, given as "transformation" equations. A transformation
10447 * looks like this: [KK*] => [Ks], and represents two sequences of operators
10448 * that have the same value or have the same effect in an expression. The
10449 * form to the left of the '=>' is the form being eliminated by the rule,
10450 * and the form to the right is shown to demonstrate why the form on the
10451 * left is eliminated. When the transformation has a shorter form on the
10452 * right than on the left, as with [1r] => [1], the reason for the rule
10453 * is obvious. In other cases it is important to eliminate only the form
10454 * that has a higher complexity score. If the scores are equal, such as
10455 * [rn] => [nr], we pick one that interacts favorably with other rules.
10456 * The form on the right is said to be "forced", meaning that any expressions
10457 * involving this type of calculation are "forced" to do it in the right-hand
10458 * form.
10459 * You must not "force" a form that is also eliminated by another rule!
10460 * For example, the following two rules are OK by themselves, but together
10461 * cause a problem:
10462 * [sr] => [rs]
10463 * [rs] => [sr]
10464 * However, you can also "force" a form that is also "forced" into another
10465 * form by another rule. The following two rules exemplify this:
10466 * [rn] => [nr]
10467 * [rq] => [qr]
10468 * These two rules, combined, make sure that 'r' never comes before 'n'
10469 * or 'q'; this will cause the combinations of 'r', 'n', and 'q' to be
10470 * reduced from six {[rnq], [rqn], [nrq], [nqr], [qrn], [qnr]} to
10471 * two {[nqr], [qnr]}
10472 * Each rule has a symbolset which must be present in order for that
10473 * rule to be used (in a few cases this symset is null).
10474 * symset sym mask mval */
10475 add_rule("", 'x', AM_RHS);
10476 add_rule("nr", 'n', AM_r); /* [rn] => [nr] */
10477 add_rule("", 'n', AM_n); /* [nn] => [] */
10478 add_rule("1", 'r', AM_1); /* [1r] => [1] */
10479 add_rule("", 'r', AM_r); /* [rr] => [] */
10480 add_rule("1", 's', AM_1); /* [1s] => [1] */
10481 add_rule("4", 's', AM_2); /* [2s] => [4] */
10482 add_rule("s", 's', AM_n); /* [ns] => [s] */
10483 add_rule("rs", 's', AM_r); /* [rs] => [sr] */
10484 add_rule("4^", 's', AM_sq); /* [qs] => []; [ss] => [4^] */
10485 add_rule("1", 'q', AM_1); /* [1q] => [1] */
10486 add_rule("rq", 'q', AM_r); /* [rq] => [qr] */
10487 add_rule("4v", 'q', AM_sq); /* [sq] => []; [qq] => [4v] */
10488 add_rule("", 'l', AM_1); /* [1l] => 0 */
10489 add_rule("ln", 'l', AM_r); /* [rl] => [ln] */
10490 add_rule("", 'l', AM_E); /* [El] => [] */
10491 add_rule("", 'E', AM_l); /* [lE] => [] */
10492 add_rule("Er", 'E', AM_n); /* [nE] => [Er] */
10493 add_rule("Sn", 'S', AM_n); /* [nS] => [Sn] */
10494 add_rule("C", 'C', AM_n); /* [nC] => [C] */
10495
10496 /* The operators are not included in their own require-symset string
10497 unless they are also used in the target of the forced transformation.
10498 This is important with the -O option. For example, if they specify
10499 -O+, the '+' rules will have the effect of "saving" the '+' for
10500 "a more important", i.e. irreducible, use. Of course, it doesn't
10501 actually prevent solutions from being found, it just makes them get
10502 found sooner. */
10503 add_rule("2*", '+', AM_KK); /* [KK+] => [K2*] */
10504 add_rule("*23456789", /* If our integers maxed out at an even number we
10505 wouldn't need the "*" here */
10506 '+', AM_55); /* [25+]=>[7]; [55+]=>[52*] */
10507 add_rule("+", '+', AM_jK); /* [jK+] => [Kj+] */
10508 add_rule("-", '+', AM_n); /* [n+] => [-] */
10509 add_rule("", '-', AM_KK); /* [KK-] => 0 */
10510 add_rule("1234n",'-', AM_55); /* [JK-] => [L] or [Ln] */
10511 add_rule("12345678n",
10512 '-', AM_jK); /* [35-] => [2n] */
10513 add_rule("+", '-', AM_n); /* [n-] => [+] */
10514 add_rule("s", '*', AM_KK); /* [KK*] => [Ks] */
10515 add_rule("*", '*', AM_jK); /* [jK*] => [Kj*] */
10516 add_rule("*", '*', AM_1); /* [1*] => [] */
10517 add_rule("*n", '*', AM_n); /* [n*] => [*n] */
10518 add_rule("/", '*', AM_r); /* [r*] => [/] */
10519 add_rule("1", '/', AM_KK); /* [KK/] => [1] */
10520 add_rule("r", '/', AM_1K); /* [1K/] => [Kr] */
10521 add_rule("", '/', AM_1); /* [1/] => [] */
10522 add_rule("/n", '/', AM_n); /* [n/] => [/n] */
10523 add_rule("*", '/', AM_r); /* [r/] => [*] */
10524 add_rule("", '^', AM_1); /* [1^] => [] */
10525 add_rule("s", '^', AM_2); /* [2^] => [s] */
10526 add_rule("^r", '^', AM_n); /* [n^] => [^r] */
10527 add_rule("1", '^', AM_1K); /* [1K^] => [1] */
10528 add_rule("v", '^', AM_r); /* [r^] => [v] */
10529 add_rule("", 'v', AM_1); /* [1v] => [] */
10530 add_rule("q", 'v', AM_2); /* [2v] => [q] */
10531 add_rule("vr", 'v', AM_n); /* [nv] => [vr] */
10532 add_rule("1", 'v', AM_1K); /* [1Kv] => [1] */
10533 add_rule("^", 'v', AM_r); /* [rv] => [^] */
10534 add_rule("1", 'L', AM_KK); /* [KKL] => [1] */
10535 add_rule("", 'L', AM_1); /* [1L] => undefined */
10536 add_rule("Ln", 'L', AM_r); /* [rL] => [Ln] */
10537 add_rule("", 'L', AM_1K); /* [1KL] => 0 */
10538
10539 if (k_sincos_arg_scale == 1.0) {
10540 /* Added on 20070511 */
10541 add_rule("", 'S', AM_pi); /* [pS] => 0 */
10542 /* Added on 20090513 */
10543 add_rule("1n", 'C', AM_pi); /* [pC] => [1n] */
10544 }
10545
10546 /* Added on 20090513 */
10547 add_rule("", '/', AM_KxK);/* [K*K/] -> [] */
10548
10549 /* Added on 20111230 */
10550 add_rule("", '-', AM_KpK);/* [K+K-] -> [] */
10551
10552 /* 20130130: The commutative operators + and * have the property
10553 that A+(B+C) = (A+B)+C. Thus, we can add a rule that forces
10554 one or the other of these two forms; the easier one to force
10555 is left-hand associative, i.e. do each operation as soon as
10556 possible. */
10557 add_rule("", '+', AM_plus); /* [ABC++] -> [AB+C+] */
10558 add_rule("", '*', AM_mul); /* [ABC**] -> [AB*C*] */
10559
10560 /* 20130130: Here we force A^(B*C) into the equivalent form
10561 (A^B)^C, which is only available if more than one ^ symbol
10562 is allowed. */
10563 add_rule("^", '^', AM_mul); /* [ABC*^] -> [AB^C^] */
10564
10565 /* 20130130: [AB^q] = sqrt(A^B) is the same as [AqB^] = sqrt(A)^B */
10566 add_rule("", 'q', AM_pow); /* [AB^q] -> [AqB^] */
10567
10568 /* 20141212: [2E]->[es], e.g. 1.07822380518236 finds xfLr = 2E1- */
10569 add_rule("es", 'E', AM_2); /* [2E] => [es] */
10570 add_rule("E", '^', AM_a1_e); /* [e..^] => [..E] */
10571
10572 /* 20141213 If I disable these I can find examples with the
10573 #search1# script, e.g. the command ./search1 es '1ab/'
10574 found that "ries 3.31130856083748 -F0 -n999 -l3 --no-refinement --max-match-distance 1e-6" gave the result "x4xr-+ = 31pq/v" */
10575 add_rule("", '*', AM_a1_1); /* [1..*] => [..] */
10576 add_rule("r", '/', AM_a1_1); /* [1../] => [..r] */
10577
10578 /* 20141215 More redundancy found via ./search1 es '[1r]ab*[v^]' */
10579 add_rule("", 'v', AM_a1_r); /* [r..v] => [..vr] */
10580 add_rule("", '^', AM_a1_r); /* [r..^] => [..^r] */
10581 add_rule("e", 'E', AM_1); /* [1E] => [e] */
10582
10583 /* Compute the weight of the most complex expression that could possibly
10584 fit in the available MAX_ELEN symbols */
10585 {
10586 s16 el_tmp = MAX_ELEN >> 1; /* Half, rounded down */
10587 if (MAX_ELEN & 1) {
10588 /* Odd max length: most cplx is of the form [aaacc] */
10589 g_exhaust_cpx = ((s16) ((el_tmp+1)*g_a_maxw + el_tmp*g_c_maxw));
10590 } else {
10591 /* Even max length: most cplx is of the form [aaabcc] */
10592 g_exhaust_cpx
10593 = ((s16) (el_tmp*g_a_maxw + g_b_maxw + (el_tmp-1)*g_c_maxw));
10594 }
10595 /* Compute the alternative using all b's i.e. [abbbbb] */
10596 el_tmp = ((s16) (g_a_maxw + (MAX_ELEN-1)*g_b_maxw));
10597 /* See if the [abbbbb] complexity is bigger */
10598 if (el_tmp > g_exhaust_cpx) {
10599 g_exhaust_cpx = el_tmp;
10600 }
10601 }
10602
10603 /* This init is for ge_2. */
10604 for(i=0; i<SYMBOL_RANGE; i++) {
10605 sym_attrs[i].sa_ct = 0;
10606 }
10607
10608 /* calculate "overflow" (really roundoff error) limits */
10609 p_ovr = fabs((ries_dif)g_target) / k_prune_deriv;
10610 n_ovr = - p_ovr;
10611
10612 g_matches = 0;
10613 if(!(g_refinement)) {
10614 size_t n_exprs_space; /* Number of symbols for g_max_matches eqns */
10615
10616 /* Allocate a block to hold the "delta" values of all reported eqns */
10617 g_mtch_alloc = ((size_t)g_max_matches) * sizeof(ries_val);
10618 g_nr_deltas = (ries_val *) malloc(g_mtch_alloc);
10619 if (g_nr_deltas == 0) {
10620 fprintf(stderr, "%s: Could not allocate %ld bytes for %ld matches.\n"
10621 "\n\n", g_argv0, (long)g_mtch_alloc, (long)g_max_matches);
10622 exit(-1);
10623 }
10624 /* g_nr_deltas never gets reallocated, because we never store more
10625 than g_max_matches into it. This global defaults to DEFAULT_MAX_MATCHES
10626 and can be altered by the --max-matches or -n option. */
10627
10628 /* Allocate a block to hold a list of all matched equations. */
10629 n_exprs_space = ((size_t)g_max_matches) * ((size_t) (MAX_ELEN+1));
10630 /* Figure out how many symbols worth of space we want */
10631 g_mtch_alloc = n_exprs_space;
10632 if (g_solve_for_x) {
10633 /* We need to store every match twice, once to prune before doing
10634 newton, and again to prune after doing try_solve */
10635 g_mtch_alloc += n_exprs_space;
10636 }
10637 if ((out_expr_format == OF_CONDENSED) || (out_expr_format == OF_NORMAL)) {
10638 /* In this situation we also add every match in infix_1 format, which
10639 can be 4 times as long as internal format */
10640 g_mtch_alloc += (n_exprs_space * 4);
10641 }
10642
10643 g_matches = (symbol *) malloc(g_mtch_alloc * sizeof(symbol));
10644 if (g_matches == 0) {
10645 fprintf(stderr, "%s: Could not allocate %ld bytes for %ld matches.\n"
10646 "\n\n", g_argv0, (long)(g_mtch_alloc * sizeof(symbol)),
10647 (long)g_max_matches);
10648 exit(-1);
10649 }
10650 symstrncat(g_matches, ((symbol *) " "), 2);
10651 mem_used_KiB = mem_used_KiB + (long)((g_mtch_alloc * sizeof(symbol))>>10);
10652 /* Carefully track memory usage */
10653 mem_used_bytes += (2 * sizeof(symbol));
10654 }
10655
10656 if (g_target == 0) {
10657 fprintf(stderr, "%s: Target number cannot be zero.\n", g_argv0);
10658 exit(-1);
10659 }
10660} /* End of init.2() */
10661
10662int g_got_target;
10663
10664/* Parse out a number from a string and set g_target and g_targ_tags based
10665 on the result.
10666
10667This is a fancy version of sscanf. The additional functions it
10668provides over sscanf are:
10669 * Comma and period are both accepted as a decimal point
10670 * Blank spaces are allowed between digits
10671 * It computes the magnitude of the ULP (unit in the last place)
10672 of the mantissa, which is needed for the --mad option
10673 */
10674int parse_target(char *str)
10675{
10676 int nv;
10677 size_t slen;
10678 char * s;
10679 char * last_digit;
10680 ries_val targ;
10681
10682 nv = 0; /* Default return value is "failure" */
10683 g_mag_ulp = 0; /* By default, the ULP measurement is zero, which will
10684 / prevent use of --mad */
10685
10686 /* Copy the string, leaving out any blank spaces and changing ',' to '.' */
10687 slen = strlen(str);
10688 s = (char *) malloc(slen+1);
10689 {
10690 unsigned int i, j;
10691 for(i=0, j=0; i<slen; i++) {
10692 if (str[i] == ' ') {
10693 /* skip */
10694 } else if (str[i] == ',') {
10695 /* treat ',' as a decimal point */
10696 s[j++] = '.';
10697 } else {
10698 s[j++] = str[i];
10699 }
10700 s[j] = 0;
10701 }
10702 }
10703
10704 /* Now we painstakingly match against legal numeric format, making note of
10705 where the final mantissa digit lies. */
10706 {
10707 int i, going;
10708 int num_dots, init_sig;
10709 char section;
10710 last_digit = 0;
10711 section = 'b'; /* beginning */
10712 num_dots = 0; init_sig = 1;
10713 i = 0; going = 1;
10714 while(s[i] && going) {
10715 if (section == 'b') {
10716 /* We're at the beginning */
10717 if ((s[i] == '+') || (s[i] == '-')) {
10718 section = 'm'; /* mantissa */
10719 } else if (init_sig && (s[i] == '0')) {
10720 section = 'm'; /* mantissa, initial zero */
10721 last_digit = &(s[i]);
10722 } else if ((s[i] >= '0') && (s[i] <= '9')) {
10723 section = 'm'; /* mantissa */
10724 last_digit = &(s[i]);
10725 init_sig = 0;
10726 } else if (s[i] == '.') {
10727 section = 'm'; /* initial decimal point, mantissa */
10728 num_dots++;
10729 } else {
10730 s[i] = '0';
10731 going = 0;
10732 }
10733 } else if (section == 'm') {
10734 /* Previous char was in the mantissa */
10735 if ((s[i] == 'e') || (s[i] == 'E')) {
10736 section = 'e'; /* exponent */
10737 } else if (init_sig && (s[i] == '0')) {
10738 /* still in manitssa, a(nother) leading zero */
10739 last_digit = &(s[i]);
10740 } else if ((s[i] >= '0') && (s[i] <= '9')) {
10741 /* still in manitssa, another digit */
10742 last_digit = &(s[i]);
10743 init_sig = 0;
10744 } else if ((num_dots == 0) && (s[i] == '.')) {
10745 /* still in mantissa, decimal point */
10746 num_dots++;
10747 } else {
10748 /* This would be an error */
10749 s[i] = '0';
10750 going = 0;
10751 }
10752 } else {
10753 /* We're in the exponent now, so we can stop scanning */
10754 going = 0;
10755 }
10756 i++;
10757 }
10758 }
10759
10760 if (last_digit) {
10761 ries_val inc_ulp; /* value altered by one Unit in the Last Place (ulp) */
10762 /* We successfully located a last digit, so we can use the converted
10763 string to get the target number. */
10764 nv = sscanf(s, RV_SS_FMT, &targ);
10765 if (nv) {
10766 /* So far, so good. Now try altering the last digit. Whenever possible
10767 we want to diminish this digit, to avoid bumping up the base-2
10768 exponent. */
10769 if (*last_digit == '0') {
10770 *last_digit = '1';
10771 } else {
10772 *last_digit = (char)((*last_digit) - 1);
10773 }
10774 if (sscanf(s, RV_SS_FMT, &inc_ulp)) {
10775 if (inc_ulp > targ) {
10776 g_mag_ulp = (ries_dif) (inc_ulp - targ);
10777 } else {
10778 g_mag_ulp = (ries_dif) (targ - inc_ulp);
10779 }
10780 if (g_mag_ulp == 0) {
10781 /* This happens when they give more decimal digits than RIES'
10782 native float format can represent. This case should be used to
10783 report that the --mad option is not realistic.
10784 We could handle this as "--max-match.distance 0" meaning that
10785 only an exact solution is accepted, but it's safer to assume we
10786 don't know the exact value of the last digit(s) and therefore
10787 cannot match them. */
10788 }
10789 } else {
10790 printf("%s: could not parse target value (as altered for ULP check)\n",
10791 g_argv0);
10792 nv = 0;
10793 }
10794
10795 g_target = targ;
10796 }
10797 }
10798
10799 free(s);
10800
10801 /* Tell the caller whether we got something */
10802 return nv;
10803} /* End of parse.target */
10804
10805void set_debug_opts(char * str)
10806{
10807 char d;
10808 while((d = *str)) {
10809 switch(d) {
10810 case 'a': debug_A |= DBG_RHS; break;
10811 case 'b': debug_B |= DBG_RHS; break;
10812 case 'c': debug_C |= DBG_RHS; break;
10813 case 'd': debug_D |= DBG_RHS; break;
10814 case 'e': debug_E |= DBG_RHS; break;
10815 case 'f': debug_F |= DBG_RHS; break;
10816 case 'g': debug_G |= DBG_RHS; break;
10817 case 'h': debug_H |= DBG_RHS; break;
10818 case 'i': debug_I |= DBG_RHS; break;
10819 case 'j': debug_J |= DBG_RHS; break;
10820 case 'k': debug_K |= DBG_RHS; break;
10821 case 'l': debug_L |= DBG_RHS; break;
10822 case 'm': debug_m = 1; break;
10823 case 'M': debug_M = 1; break;
10824 case 'n': debug_n = 1; break;
10825 case 'N': debug_N = 1; break;
10826 case 'o': debug_o = 1; break;
10827 case 'p': debug_p = 1; break;
10828 case 'q': debug_q = 1; break;
10829 case 'r': debug_r = 1; break;
10830 case 's': debug_s = 1; break;
10831 case 't': debug_t = 1; break;
10832 case 'u': debug_u = 1; break;
10833 case 'v': debug_v = 1; break;
10834 case 'w': debug_w = 1; break;
10835 case 'x': debug_x = 1; break;
10836 case 'y': debug_y = 1; break;
10837 case 'z': debug_z = 1; break;
10838 case 'A': debug_A |= DBG_LHS; break;
10839 case 'B': debug_B |= DBG_LHS; break;
10840 case 'C': debug_C |= DBG_LHS; break;
10841 case 'D': debug_D |= DBG_LHS; break;
10842 case 'E': debug_E |= DBG_LHS; break;
10843 case 'F': debug_F |= DBG_LHS; break;
10844 case 'G': debug_G |= DBG_LHS; break;
10845 case 'H': debug_H |= DBG_LHS; break;
10846 case 'I': debug_I |= DBG_LHS; break;
10847 case 'J': debug_J |= DBG_LHS; break;
10848 case 'K': debug_K |= DBG_LHS; break;
10849 case 'L': debug_L |= DBG_LHS; break;
10850 case 'Q': debug_Q = 1; break;
10851 case 'S': debug_S = 1; break;
10852 case '0': debug_0 = 1; break;
10853 default: break;
10854 }
10855 str++;
10856 }
10857} /* End of set.debug_opts */
10858
10859/* Summary of how each of the restricted class options is implemented
10860
10861 Option -i -r -c -a -l
10862 g_restrict_subexpr INT RAT CONS ALG TRAN
10863 g_restrict_exponents RAT ELEM
10864 g_restrict_trig_args RAT ELEM
10865 set_restrict_rat *
10866 set_restrict_alg 1 0
10867 somesyms_set:
10868 digits * * * * *
10869 +-* /nr * * * * *
10870 sqf * * *
10871 x 1 1 1 * *
10872 ^vSCT * *
10873 eplEL *
10874 */
10875
10876/* Restrict to rational subexpressions. This is invoked by the -r
10877option and when we switch to -r after getting -i with a non-integer
10878target. */
10879void set_restrict_rat(void)
10880{
10881 g_restrict_subexpr = TYPE_RAT;
10882 somesyms_set((symbol *) "pefqSCTlvLEW", 0);
10883 somesyms_set((symbol *) "+-*/nr", MAX_ELEN);
10884 somesyms_set((symbol *) "x", 1);
10885 somesyms_set((symbol *) "s^", 0); /* %%% Once I improve LHS vs RHS
10886 symbolset handling, I can enable [s] on RHS and on
10887 non-x-containing subexpressions in LHS, and I can
10888 allow q to be appended to LHS if and only if the
10889 stack is 1. I can do the same thing for ^ and v
10890 if I also implement an "integer arguments" option. */
10891}
10892
10893/* Restrict to algebraic roots. This is invoked by the -a and -l options. */
10894void set_restrict_alg(int restrict_trig)
10895{
10896 g_restrict_subexpr = TYPE_ALG;
10897 /* This option is mostly achieved by turning off transcendental
10898 functions. */
10899 somesyms_set((symbol *) "pelLEW", 0);
10900 /* Unlike with the smaller classes (constructible, rational) we allow
10901 more than one x in the solution */
10902 somesyms_set((symbol *) "+-*/nrsqfx", MAX_ELEN);
10903 /* Exponents are okay as long as we use only rational exponents.
10904 The implementation of g_restrict_exponents also disallows x
10905 in an exponent. */
10906 /* %%% It might be nice to have a restriction permitting integer exponents
10907 of x if the exponent is 5 or less, which would let us offer an
10908 "algebraic closed-form" class. For now, -Ox is the only way to get
10909 a guarantee of closed-form roots. */
10910 somesyms_set((symbol *) "^v", MAX_ELEN);
10911 g_restrict_exponents = TYPE_RAT;
10912 /* Trig functions are okay as long as we restrict their arguments
10913 to rational multiples of pi (and g_restrict_trig_args also
10914 disallows x inside a trig function). */
10915 somesyms_set((symbol *) "SCT", MAX_ELEN);
10916 if (restrict_trig) {
10917 g_restrict_trig_args = TYPE_RAT;
10918 k_sincos_arg_scale = k_pi;
10919 g_trig_scale_default = B_TRUE;
10920 }
10921} /* End of set.restrict_alg */
10922
10923# define MAX_FILE_DEPTH 27
10924size_t stk_nargs[MAX_FILE_DEPTH];
10925char * * stk_argv[MAX_FILE_DEPTH];
10926int pa_sp;
10927char * pa_this_arg;
10928int pa_argnum;
10929
10930/* Look for a default setting file, and if one exists, return a pointer
10931 to its pathname with "-p" in front. This allocates a block of memory,
10932 and is only called once. */
10933char * pa_defaults_path(void)
10934{
10935 char * hd;
10936 char * pdp;
10937 char sep;
10938 FILE * f;
10939
10940#ifdef _WIN32
10941 hd = getenv("USERPROFILE");
10942 sep = '\\';
10943#else
10944 hd = getenv("HOME");
10945 sep = '/';
10946#endif
10947 if (hd) {
10948 size_t plen;
10949 /* Allocate enough space to copy the directory, plus a leading "-p",
10950 a directory separator character '/' or '\\', and filename e.g.
10951 "ries_profile.txt" plus trailing null */
10952 plen = sizeof(char) * (strlen(hd) + 100);
10953 pdp = (char *) malloc(plen);
10954 if (pdp) {
10955 /* Copy the environment variable while adding all the rest */
10956 snprintf(pdp, plen, "-p%s%c%s", hd, sep, "ries_profile.txt");
10957 /* Try to open it */
10958 if (f = fopen(pdp+2,"r"), f) {
10959 /* Successful: close the file and return the string pointer */
10960 fclose(f); return pdp;
10961 }
10962 /* That filename did not work; try again with ".ries_profile" */
10963 snprintf(pdp, plen, "-p%s%c%s", hd, sep, ".ries_profile");
10964 if (f = fopen(pdp+2,"r"), f) {
10965 fclose(f); return pdp;
10966 }
10967 }
10968 }
10969 return 0;
10970} /* End of pa.defaults_path */
10971
10972/* Return a pointer to the next argument, or a null string if there
10973 are no more arguments on the present stack. */
10974char * pa_next_peek(void)
10975{
10976 if (pa_sp < 0) {
10977 return ((char *) "");
10978 }
10979 if (stk_nargs[pa_sp] <= 0) {
10980 /* No more arguments at this level. Note in particular we do not allow
10981 an argument in a profile to take a parameter from the argument list
10982 that included it. */
10983 return ((char *) "");
10984 }
10985 return(*(stk_argv[pa_sp]));
10986}
10987
10988/* Returns true if the next argument (as given by pa_next_peek) is a non-null
10989 string beginning with '-' */
10990int pa_next_isparam(void)
10991{
10992 char * p;
10993
10994 p = pa_next_peek();
10995 if (p && p[0] && (p[0] != '-')) {
10996 return 1;
10997 }
10998 return 0;
10999}
11000
11001char * pa_get_arg(void)
11002{
11003 char * rv;
11004 if (pa_sp < 0) {
11005 rv = 0;
11006 } else if (stk_nargs[pa_sp] <= 0) {
11007 rv = 0;
11008 } else {
11009 rv = *(stk_argv[pa_sp]);
11010 (stk_argv[pa_sp])++;
11011 (stk_nargs[pa_sp])--;
11012 }
11013 pa_this_arg = rv;
11014 return rv;
11015}
11016
11017char * pa_stk_pop(void)
11018{
11019 pa_sp--;
11020 if (pa_sp < 0) {
11021 pa_this_arg = 0;
11022 } else if (stk_nargs[pa_sp] <= 0) {
11023 pa_this_arg = 0;
11024 } else {
11025 pa_this_arg = *(stk_argv[pa_sp]);
11026 }
11027 return pa_this_arg;
11028} /* End of pa_stk_pop */
11029
11030/* Scan argv, parsing and executing arguments. When a --include/-p argument
11031 is encountered, open and scan the indicated file. Recursion is implemented
11032 by an explicit stack; this function does not call itself recursively. */
11033void parse_args(size_t nargs, char *argv[])
11034{
11035 int nv; /* Number of values returned by a sscanf */
11036 int do_getarg;
11037
11038 {
11039 /* Skip our program name/path */
11040 argv++;
11041 nargs--;
11042
11043 /* Initialize the stack */
11044 pa_sp = 0;
11045 pa_argnum = 0;
11046 stk_nargs[pa_sp] = nargs;
11047 stk_argv[pa_sp] = argv;
11048 }
11049
11050 pa_def_path = pa_defaults_path();
11051
11052 while(pa_sp >= 0) {
11053 /* First figure out if we're going to auto-load the defaults */
11054 do_getarg = 1;
11055 if (pa_argnum == 0) {
11056 if (strcmp(pa_next_peek(), "-p") != 0) {
11057 /* They did *not* give an initial '-p' */
11058 if (pa_def_path) {
11059 pa_this_arg = pa_def_path;
11060 /* printf("Starting with defaults: %s\n", pa_this_arg); */
11061 do_getarg = 0;
11062 }
11063 }
11064 }
11065
11066 /* Get the next argument at the present stacklevel */
11067 if (do_getarg) {
11068 pa_get_arg(); /* Sets pa_this_arg */
11069 }
11070 pa_argnum++;
11071
11072 if (pa_this_arg == 0) {
11073 /* This happens if pa_get_arg has run out of args or if it gets an
11074 arg that is a null string. Either case means we should pop */
11075 pa_stk_pop();
11076 } else if (strcmp(pa_this_arg, "--ries-arguments-end") == 0) {
11077 /* Ignore any more arguments at this level */
11078 pa_stk_pop();
11079
11080 } else if ((strncmp(pa_this_arg, "-p", 2) == 0)
11081 || (strcmp(pa_this_arg, "--include") == 0)) {
11082 /* load Parameters (or "Profile") from a file */
11083
11084 /* First check for a bare '-p' and not on the first arg; if so and
11085 if there is a defaults file, we use it. */
11086 if (strcmp(pa_this_arg, "-p") == 0) {
11087 if (pa_argnum <= 1) {
11088 /* -p on the first arg means do not load the defaults; this will
11089 have already been handled so all we need to do now is ignore
11090 the option. */
11091 pa_this_arg = 0;
11092 } else {
11093 if (pa_def_path) {
11094 pa_this_arg = pa_def_path;
11095 } else {
11096 /* They gave a bare '-p' but there is no profile */
11097 printf(
11098 "%s: got -p option, but could not find .ries_profile or"
11099 " ries_profile.txt\n"
11100 "in home directory.\n",
11101 g_argv0);
11102 brief_help();
11103 print_end(-1);
11104 }
11105 }
11106 }
11107
11108 if (pa_this_arg && strcmp(pa_this_arg, "--include") == 0) {
11109 pa_get_arg();
11110 if (pa_this_arg == 0) {
11111 printf(
11112 "%s: --include requires a filename, e.g. '--include trig.ries'\n"
11113 "\n",
11114 g_argv0);
11115 brief_help();
11116 print_end(-1);
11117 }
11118 } else if (pa_this_arg) {
11119 pa_this_arg += 2; /* skip the "-p" */
11120 }
11121 if (pa_this_arg && *pa_this_arg) {
11122 char * filebuf;
11123 size_t n;
11124 char * * av;
11125 filebuf = file_read(pa_this_arg);
11126 delimit_args(filebuf, &n, &av);
11127 if (n) {
11128 if ((pa_sp+1) < MAX_FILE_DEPTH) {
11129 /* Push new set of args onto the stack */
11130 pa_sp++;
11131 stk_nargs[pa_sp] = n;
11132 stk_argv[pa_sp] = av;
11133 } else {
11134 printf("%s: -p parameters nested too deep (max %d levels).\n"
11135 "\n", g_argv0, MAX_FILE_DEPTH);
11136 brief_help();
11137 print_end(-1);
11138 }
11139 } else {
11140 /* File had no tokens; we could complain but we let it pass. */
11141 }
11142 } else if (pa_this_arg) {
11143 printf(
11144 "%s: -p parameter requires a filename, e.g. '-ptrig.ries'\n"
11145 "\n", g_argv0);
11146 brief_help();
11147 print_end(-1);
11148 }
11149
11150 } else if (strcmp(pa_this_arg, "-") == 0) {
11151 /* Null option, useful for ending a string of numeric arguments,
11152 as e.g. after the --eval-expression option, before giving the
11153 target number. */
11154
11155 /* First we check the "--foo-bar VAL" type options, in which the
11156 "opcode" and its "arguments" are each separate elements of argv[].
11157 These are used for special or rarely-used commands, like the
11158 command that gives an expression's complexity score */
11159
11160
11161 } else if (strcmp(pa_this_arg, "--any-exponents") == 0) {
11162 g_restrict_exponents = TYPE_NONE;
11163
11164 } else if (strcmp(pa_this_arg, "--any-subexpressions") == 0) {
11165 g_restrict_subexpr = TYPE_NONE;
11166
11167 } else if (strcmp(pa_this_arg, "--any-trig-args") == 0) {
11168 g_restrict_trig_args = TYPE_NONE;
11169
11170 } else if (strcmp(pa_this_arg, "--canon-reduction") == 0) {
11171 if (pa_next_isparam()) {
11172 /* Set which types of canonval reduction to use. */
11173 char * s;
11174 s = pa_get_arg();
11175 if (s) {
11176 g_canon_ops = 0;
11177 while(*s) {
11178 switch(*s) {
11179 case 'n': ; g_canon_ops |= CANONVAL_NEGATE; break;
11180 case 'r': ; g_canon_ops |= CANONVAL_RECIPROCAL; break;
11181 case '2': ; g_canon_ops |= CANONVAL_MUL2; break;
11182 case '5': ; g_canon_ops |= CANONVAL_DIV2; break;
11183 default: ; break;
11184 }
11185 s++;
11186 }
11187 }
11188 } else {
11189 printf("%s: --canon-reduction requires a set of reduction types, "
11190 "e.g. 'nr25'\n"
11191 "\n", g_argv0);
11192 brief_help();
11193 print_end(-1);
11194 }
11195
11196 } else if (strcmp(pa_this_arg, "--canon-simplify") == 0) {
11197 g_no_cv_simplify = B_FALSE;
11198
11199 } else if (strcmp(pa_this_arg, "--derivative-margin") == 0) {
11200 /* Override default value of k_vanished.dx */
11201 ries_dif t;
11202 pa_get_arg();
11203 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11204 if (t < 0) {
11205 printf("%s: --derivative-margin must be positive (I got %g).\n"
11206 "\n", g_argv0, t);
11207 brief_help();
11208 print_end(-1);
11209 } else if (t > 1.0e-4) {
11210 /* Too large */
11211 printf("%s: --derivative-margin value should be at most 1.0e-4.\n"
11212 "\n", g_argv0);
11213 brief_help();
11214 print_end(-1);
11215 } else {
11216 k_derivative_margin = t;
11217 printf("Allowing d/dx to be as small as value times %g.\n",
11218 k_derivative_margin);
11219 }
11220 } else {
11221 printf("%s: --derivative-margin should be followed by a numeric "
11222 "argument.\n"
11223 "\n", g_argv0);
11224 brief_help();
11225 print_end(-1);
11226 }
11227
11228 } else if (strcmp(pa_this_arg, "--eval-expression") == 0) {
11229 if (pa_next_isparam()) {
11230 /* This is used to check FORTH expression syntax; it is a complement
11231 to --find-expression and some of the other command options
11232 like -F0 and -DGg */
11233 while(pa_next_isparam()) {
11234 if (g_num_find_expr > MAX_FIND_EXPR) {
11235 printf("%s: --eval-expression takes at most %d arguments.\n",
11236 g_argv0, MAX_FIND_EXPR);
11237 brief_help();
11238 print_end(-1);
11239 }
11240 g_find_expr[g_num_find_expr] = (symbol *) pa_get_arg();
11241 g_num_find_expr++;
11242 }
11243 g_enable_output = 0;
11244 g_eval_expr = 1;
11245 } else {
11246 printf("%s: --eval-expression should be followed by compact "
11247 "postfix expression(s).\n"
11248 "\n", g_argv0);
11249 brief_help();
11250 print_end(-1);
11251 }
11252
11253 } else if (strcmp(pa_this_arg, "--explicit-multiply") == 0) {
11254 g_explicit_multiply = B_TRUE;
11255
11256 } else if (strcmp(pa_this_arg, "--find-expression") == 0) {
11257 if (pa_next_isparam()) {
11258 /* This is used to scan for one of more expression(s) and print
11259 out their stats, in whatever order they happen to be found. This
11260 is an easier-to-use replacement for the -DGg option filtered
11261 through grep. */
11262 while(pa_next_isparam()) {
11263 if (g_num_find_expr > MAX_FIND_EXPR) {
11264 printf("%s: --find-expression takes at most %d arguments.\n",
11265 g_argv0, MAX_FIND_EXPR);
11266 brief_help();
11267 print_end(-1);
11268 }
11269 g_find_expr[g_num_find_expr] = (symbol *) pa_get_arg();
11270 g_num_find_expr++;
11271 }
11272 g_enable_output = 0;
11273 } else {
11274 printf("%s: --find-expression should be followed by compact "
11275 "postfix expression(s).\n"
11276 "\n", g_argv0);
11277 brief_help();
11278 print_end(-1);
11279 }
11280
11281 } else if ((strcmp(pa_this_arg, "--match-all-digits") == 0)
11282 || (strcmp(pa_this_arg, "--mad") == 0)
11283 ) {
11284 g_match_all_digits = B_TRUE;
11285 k_max_match_dist = -0.01; /* This will be calculated from the target
11286 by init.2 */
11287
11288 } else if (strcmp(pa_this_arg, "--max-equate-value") == 0) {
11289 ries_val t;
11290 pa_get_arg();
11291 if (pa_this_arg && sscanf(pa_this_arg, RV_SS_FMT, &t)) {
11292 if (t <= g_min_equ_val) {
11293 printf("%s: --max-equate-value argument cannot be greater than "
11294 "--min-equate-value argument.\n", g_argv0);
11295 brief_help();
11296 print_end(-1);
11297 }
11298 g_max_equ_val = t;
11299 printf("Equations will have both sides at most ");
11300 spfg(k_usable_digits, g_max_equ_val);
11301 printf("\n");
11302 } else {
11303 printf("%s: --max-equate-value should be followed by a numeric "
11304 "argument.\n"
11305 "\n", g_argv0);
11306 brief_help();
11307 print_end(-1);
11308 }
11309
11310 } else if (strcmp(pa_this_arg, "--max-match-distance") == 0) {
11311 ries_dif t;
11312 pa_get_arg();
11313 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11314 k_max_match_dist = t;
11315 g_match_all_digits = B_FALSE; /* Cannot use both options together */
11316 if (k_max_match_dist < 0) {
11317 printf(
11318 "First match must be closer than %g times your target value.\n",
11319 -k_max_match_dist);
11320 } else if (k_max_match_dist == 0) {
11321 printf("Only give an 'exact' match (if any) then exit.\n");
11322 } else {
11323 printf("First match must be closer than %g.\n", k_max_match_dist);
11324 }
11325 } else {
11326 printf("%s: --max-match-distance should be followed by a numeric "
11327 "argument.\n"
11328 "\n", g_argv0);
11329 brief_help();
11330 print_end(-1);
11331 }
11332
11333 } else if ((strcmp(pa_this_arg, "--max-matches") == 0)
11334 || (strncmp(pa_this_arg, "-n", 2) == 0)) {
11335 double t;
11336 if (pa_this_arg[1] == 'n') {
11337 pa_this_arg += 2; /* Skip the '-n' */
11338 } else {
11339 pa_get_arg(); /* Get the next arg */
11340 }
11341 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11342 if (t >= 1) {
11343 g_max_matches = (stats_count) t;
11344 } else {
11345 printf("%s: -n or --max-matches argument should be 1 or more.\n"
11346 "examples: -n7 or --max-matches 7\n"
11347 "\n", g_argv0);
11348 brief_help();
11349 print_end(-1);
11350 }
11351 } else {
11352 printf("%s: --max-matches should be followed by a numeric "
11353 "argument.\n"
11354 "examples: -n7 or --max-matches 7\n"
11355 "\n", g_argv0);
11356 brief_help();
11357 print_end(-1);
11358 }
11359
11360 } else if (strcmp(pa_this_arg, "--max-memory") == 0) {
11361 time_flt t;
11362 pa_get_arg();
11363 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11364 g_max_memory = fabs(t);
11365 printf("Will not use more than %g bytes of memory.\n",
11366 g_max_memory);
11367 } else {
11368 printf("%s: --max-memory should be followed by a numeric argument.\n"
11369 "\n", g_argv0);
11370 brief_help();
11371 print_end(-1);
11372 }
11373
11374 } else if (strcmp(pa_this_arg, "--memory-abort-threshold") == 0) {
11375 time_flt t;
11376 pa_get_arg();
11377 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11378 if (t > 1.0) {
11379 g_mem_bad_ratio = t;
11380 printf("Memory slowness abort ratio: %g.\n",
11381 g_mem_bad_ratio);
11382 } else {
11383 printf("%s: --memory-abort-threshold should be at least 1.0,"
11384 " and values less than about 1.5 are unlikely to be of"
11385 " much use.\n"
11386 "\n", g_argv0);
11387 brief_help();
11388 print_end(-1);
11389 }
11390 } else {
11391 printf(
11392 "%s: --memory-abort-threshold should be followed by a numeric\n"
11393 "argument larger than 1.0 (larger than 1.5 is recommended).\n"
11394 "\n", g_argv0);
11395 brief_help();
11396 print_end(-1);
11397 }
11398
11399 } else if (strcmp(pa_this_arg, "--min-equate-value") == 0) {
11400 ries_val t;
11401 pa_get_arg();
11402 if (pa_this_arg && sscanf(pa_this_arg, RV_SS_FMT, &t)) {
11403 if (t >= g_max_equ_val) {
11404 printf("%s: --min-equate-value argument cannot be greater than "
11405 "--max-equate-value argument.\n", g_argv0);
11406 brief_help();
11407 print_end(-1);
11408 }
11409 g_min_equ_val = t;
11410 printf("Equations will have both sides at least ");
11411 spfg(k_usable_digits, g_min_equ_val);
11412 printf("\n");
11413 } else {
11414 printf("%s: --min-equate-value should be followed by a numeric "
11415 "argument.\n"
11416 "\n", g_argv0);
11417 brief_help();
11418 print_end(-1);
11419 }
11420
11421 } else if (strcmp(pa_this_arg, "--min-match-distance") == 0) {
11422 /* %%% I might want to have "-ee" be a synonym for
11423 "--max-match-distance 0" */
11424 ries_dif t;
11425 pa_get_arg();
11426 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11427 g_min_matchsize = t;
11428 if (g_min_matchsize == 0.0) {
11429 printf("Will exit if an 'exact' match is found.\n");
11430 g_exact_exit = B_TRUE;
11431 } else if (g_min_matchsize < -0.1) {
11432 printf("%s: --min-match-distance argument can be negative but not "
11433 "less than -0.1\n"
11434 "\n", g_argv0);
11435 brief_help();
11436 print_end(-1);
11437 } else if (g_min_matchsize < 0.0) {
11438 printf("Using a minimum match distance of %g times your "
11439 "target value.\n", g_min_matchsize);
11440 } else {
11441 printf("Using minimum match distance: %g\n", g_min_matchsize);
11442 }
11443 } else {
11444 printf("%s: --min-match-distance should be followed by a numeric "
11445 "argument.\n"
11446 "\n", g_argv0);
11447 brief_help();
11448 print_end(-1);
11449 }
11450
11451 } else if (strcmp(pa_this_arg, "--min-memory") == 0) {
11452 time_flt t;
11453 pa_get_arg();
11454 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11455 g_min_memory = fabs(t);
11456 printf("Memory-hogging safeguard disabled for the first %g bytes.\n",
11457 g_min_memory);
11458 } else {
11459 printf("%s: --min-memory should be followed by a numeric "
11460 "argument.\n"
11461 "\n", g_argv0);
11462 brief_help();
11463 print_end(-1);
11464 }
11465
11466 } else if (strcmp(pa_this_arg, "--no-canon-simplify") == 0) {
11467 g_no_cv_simplify = B_TRUE;
11468
11469 } else if (strcmp(pa_this_arg, "--no-refinement") == 0) {
11470 g_refinement = 0;
11471
11472 } else if (strcmp(pa_this_arg, "--no-slow-messages") == 0) {
11473 g_allow_slow_message = 0;
11474
11475 } else if (strcmp(pa_this_arg, "--no-solve-for-x") == 0) {
11476 g_solve_for_x = B_FALSE;
11477
11478 } else if (strcmp(pa_this_arg, "--numeric-anagram") == 0) {
11479 if (pa_next_isparam()) {
11480 /* Remember the selected anagram string, we test this later */
11481 g_anagram = (char *) pa_get_arg();
11482 /* Set the sym_allowed values */
11483 set_anagram(g_anagram);
11484 } else {
11485 printf(
11486 "%s: --numeric-anagram should be followed by a string of digits.\n"
11487 "\n", g_argv0);
11488 brief_help();
11489 print_end(-1);
11490 }
11491
11492 } else if (strcmp(pa_this_arg, "--one-sided") == 0) {
11493 g_one_sided = B_TRUE;
11494
11495 } else if (strcmp(pa_this_arg, "--rational-exponents") == 0) {
11496 g_restrict_exponents = TYPE_RAT;
11497
11498 } else if (strcmp(pa_this_arg, "--rational-trig-args") == 0) {
11499 g_restrict_trig_args = TYPE_RAT;
11500
11501 } else if (strcmp(pa_this_arg, "--relative-roots") == 0) {
11502 /* Show "x = T + epsilon" rather than absolute values */
11503 if (g_match_all_digits) {
11504 printf("Note: Ignoring '%s' because '--match-all-digits' is set.\n",
11505 pa_this_arg);
11506 } else {
11507 g_relative_x = B_TRUE;
11508 }
11509
11510 } else if (strcmp(pa_this_arg, "--significance-loss-margin") == 0) {
11511 ries_dif t;
11512 pa_get_arg();
11513 if (pa_this_arg && sscanf(pa_this_arg, "%lf", &t)) {
11514 if ((t >= 0.0) && (t < 100.0)) {
11515 t = pow(10.0, -t);
11516 k_sig_loss = t;
11517 printf("Using significance loss margin: %g\n", k_sig_loss);
11518 } else {
11519 printf("%s: --significance-loss-margin must be between 0.0 "
11520 "and 100.0\n"
11521 "\n", g_argv0);
11522 brief_help();
11523 print_end(-1);
11524 }
11525 } else {
11526 printf(
11527 "%s: --significance-loss-margin should be followed by a numeric "
11528 "argument.\n"
11529 "\n", g_argv0);
11530 brief_help();
11531 print_end(-1);
11532 }
11533
11534 } else if (strcmp(pa_this_arg, "--symbol-names") == 0) {
11535 if (pa_next_isparam()) {
11536 char space_sym = ' ';
11537 /* Override the standard symbol names. Multiple arguments may
11538 be given. */
11539 while(pa_next_isparam()) {
11540 char * a;
11541 symbol sym;
11542 a = pa_get_arg();
11543 if ( (a[0] == ':') && a[1]
11544 && (a[2] == ':') && (a[3]==a[1]) && (a[4] == 0)
11545 && (space_sym == ' ')) {
11546 /* This syntax is used to define a symbol that stands in for
11547 blank space. */
11548 space_sym = a[1];
11549 } else if ((a[0] == ':') && a[1] && (a[2] == ':')) {
11550 sym = (symbol) a[1];
11551 if (strlen(a+3) <= MAX_SYM_NAME_LEN) {
11552 str_remap(a+3, space_sym, ' ');
11553 sym_attrs[sym].sa_name =
11554 sym_attrs[sym].name_forth = a+3;
11555 /* printf("setsym %c:%s\n", sym, a+3); */
11556 } else {
11557 printf("%s: Symbol name can be at most %d characters\n"
11558 "(I got '%s')\n", g_argv0, MAX_SYM_NAME_LEN, a+3);
11559 print_end(-1);
11560 }
11561 } else {
11562 printf("%s: --symbol-names argument syntax is :<sym>:name,"
11563 " for example\n"
11564 " :-:deme to set name of '-' to 'deme'\n"
11565 " Instead I got '%s'\n", g_argv0, a);
11566 print_end(-1);
11567 }
11568 }
11569 } else {
11570 printf(
11571 "%s: --symbol-names should be followed by one or more tuples\n"
11572 " of the form <sym>:name, for example:\n"
11573 " :-:deme to set name of '-' to 'deme'\n", g_argv0);
11574 print_end(-1);
11575 }
11576
11577 } else if (strcmp(pa_this_arg, "--symbol-weights") == 0) {
11578 if (pa_next_isparam()) {
11579 /* Override the standard symbol weights. Multiple arguments may
11580 be given. */
11581 while(pa_next_isparam()) {
11582 char * a;
11583 unsigned char argtmp[20];
11584 int i; ries_dif w;
11585 a = pa_get_arg();
11586 ries_strncpy((char *) argtmp, a, 20);
11587 /* Skip the numeric portion */
11588 for(i=0;
11589 (argtmp[i]=='.') || ((argtmp[i]>='0') && (argtmp[i]<='9'));
11590 i++ ) { }
11591 if ((argtmp[i] == ':') && (argtmp[i+1])) {
11592 argtmp[i++] = 0; /* Null-terminate the numeric portion by
11593 overwriting the ':' */
11594 w = strtod((char *) argtmp, 0);
11595 if (w <= MIN_SYMBOL_WEIGHT) {
11596 printf("%s: Symbol weight may not be %f or less.\n",
11597 g_argv0, MIN_SYMBOL_WEIGHT);
11598 print_end(-1);
11599 }
11600 if (w > MAX_SYMBOL_WEIGHT) { w = MAX_SYMBOL_WEIGHT; }
11601 /* printf("set weight of '%c' to %d\n", argtmp[i], (int) w); */
11602 sym_attrs[argtmp[i]].preempt_weight = (s16) floor(w + 0.5);
11603 } else {
11604 printf("%s: --symbol-weights argument syntax is NUMBER:<sym>,"
11605 " for example\n"
11606 " 12:^ to set weight of '^' to 12\n"
11607 " Instead I got '%s'\n", g_argv0, a);
11608 print_end(-1);
11609 }
11610 }
11611 } else {
11612 printf(
11613 "%s: --symbol-weights should be followed by one or more tuples\n"
11614 " of the form NUMBER:<sym>, for example"
11615 " 12:^ to set weight of '^' to 12\n", g_argv0);
11616 print_end(-1);
11617 }
11618
11619 } else if (strcmp(pa_this_arg, "--trig-argument-scale") == 0) {
11620 ries_val t;
11621 pa_get_arg();
11622 if (pa_this_arg && sscanf(pa_this_arg, RV_SS_FMT, &t)) {
11623 if ((t >= 0.0) && (t < 100.0)) {
11624 k_sincos_arg_scale = (ries_val) t;
11625 g_trig_scale_default = (k_sincos_arg_scale == k_pi);
11626 printf("Argument of trig functions will be scaled by ");
11627 spfg(k_usable_digits, k_sincos_arg_scale); /* printf(fmt_g_usable, k_sincos_arg_scale); */
11628 printf("\n");
11629 } else {
11630 printf("%s: --trig-argument-scale must be between 0.0 "
11631 "and 100.0\n"
11632 "\n", g_argv0);
11633 brief_help();
11634 print_end(-1);
11635 }
11636 } else {
11637 printf("%s: --trig-argument-scale should be followed by a numeric "
11638 "argument.\n"
11639 "\n", g_argv0);
11640 brief_help();
11641 print_end(-1);
11642 }
11643
11644 } else if ((strncmp(pa_this_arg, "-s", 2) == 0)
11645 || (strcmp(pa_this_arg, "--try-solve-for-x") == 0)) {
11646 g_solve_for_x = B_TRUE;
11647
11648 } else if (strcmp(pa_this_arg, "--version") == 0) {
11649 show_version();
11650 exit(0);
11651
11652 } else if ((strcmp(pa_this_arg, "--wide-output") == 0)
11653 || (strcmp(pa_this_arg, "--wide") == 0)
11654 ) {
11655 g_wide_output = B_TRUE;
11656 g_relative_x = B_TRUE;
11657
11658 /* Single-character arguments:
11659 { %% those in braces are not yet implemented }
11660 -0 to -9 target number with leading - sign
11661 -a Algebraic class
11662 -c Constructible class
11663 -D Debug
11664 { -e Elementary class (between algebraic and Liouvillian) }
11665 { -ee Exact exit (might be confused with -e plus 'exact') }
11666 -F Format
11667 -i Integer class (and -ie)
11668 -l Liouvillian (if bare); level (if with digit)
11669 -N Not these symbols
11670 -O Once-only symbols
11671 -p profile/parameters (parsed above)
11672 -r Rational class (and -re)
11673 -s (try to) solve for x
11674 -S Symbolset
11675 { -t Transcendental class (enable [W], [G], etc.) }
11676 -x Show X, not T+epsilon
11677 */
11678 /* Next we check the "-xN" type options, in which the "opcode" is a
11679 single letter and its "arguments" follow it without a space in
11680 between. These are used for the options you'll commonly want to
11681 give when invoking ries to solve a problem. */
11682
11683
11684 } else if ((strncmp(pa_this_arg, "-a", 2) == 0)
11685 || (strcmp(pa_this_arg, "--algebraic-subexpressions") == 0)) {
11686 /* Subexpressions must be algebraic numbers */
11687 set_restrict_alg(1);
11688 if (pa_this_arg[2] == 'e') {
11689 /* They gave "-ae"
11690 %%% This should instead set an epsilon as with
11691 --min-match-distance with a negative argument proportional
11692 to the ULP as measured by init.formats */
11693 g_exact_exit = B_TRUE;
11694 }
11695
11696 } else if ((strncmp(pa_this_arg, "-c", 2) == 0)
11697 || (strcmp(pa_this_arg, "--constructible-subexpressions") == 0)) {
11698 /* Subexpressions must be constructible numbers */
11699 g_restrict_subexpr = TYPE_CONS;
11700 if (pa_this_arg[2] == 'e') {
11701 /* They gave "-ce": exit on exact match.
11702 NOTE: We already set k_min_best_match proportionally
11703 to the target size */
11704 g_exact_exit = B_TRUE;
11705 }
11706 /* This option is just shorthand for turning off a bunch of
11707 functions. */
11708 somesyms_set((symbol *) "peSCTl^vLEW", 0);
11709 somesyms_set((symbol *) "+-*/nrsqf", MAX_ELEN);
11710 somesyms_set((symbol *) "x", 1);
11711 /* %%% Once I add an integer arguments option for ^, I can enable it
11712 on RHS and in non-x-containing subexpressions in LHS. */
11713
11714 } else if (strncmp(pa_this_arg, "-D", 2) == 0) {
11715 /* Debugging options */
11716 set_debug_opts(pa_this_arg+2); /* +2 to skip the "-D" */
11717
11718 } else if (strncmp(pa_this_arg, "-E", 2) == 0) {
11719 /* Enable these symbols: Like -S but doesn't clear everything else
11720 out */
11721 NOS_options = B_TRUE;
11722 somesyms_set((symbol *) (pa_this_arg+2), MAX_ELEN); /* +2 skips "-E" */
11723
11724 } else if (strncmp(pa_this_arg, "-F", 2) == 0) {
11725 /* Select expression display format */
11726 pa_this_arg += 2; /* skip the "-F" */
11727 if (*pa_this_arg == 0) {
11728 out_expr_format = OF_FORTH; /* default */
11729 } else {
11730 nv = sscanf(pa_this_arg, "%d", &out_expr_format);
11731 if (nv == 0) {
11732 printf("%s: -F parameter requires a number, e.g. '-F0'\n"
11733 "\n", g_argv0);
11734 brief_help();
11735 print_end(-1);
11736 }
11737 }
11738
11739 } else if ((strncmp(pa_this_arg, "-i", 2) == 0)
11740 || (strcmp(pa_this_arg, "--integer-subexpressions") == 0)) {
11741 /* Integer subexpressions */
11742 g_restrict_subexpr = TYPE_INT;
11743 somesyms_set((symbol *) "pefqSCTlvLEW", 0);
11744 if (pa_this_arg[2] == 'e') {
11745 /* They gave "-ie" */
11746 g_exact_exit = B_TRUE;
11747 }
11748
11749 } else if ((strncmp(pa_this_arg, "-l", 2) == 0)
11750 || (strcmp(pa_this_arg, "--liouvillian-subexpressions") == 0)) {
11751 char t;
11752 /* they gave a level */
11753 pa_this_arg += 2; /* skip the "-l" */
11754 t = pa_this_arg[0];
11755 if ((t == '-') || ((t >= '0') && (t <= '9'))) {
11756 nv = sscanf(pa_this_arg, "%lf", &g_levadj);
11757 if (nv) {
11758 tlevel = DEFAULT_LEV_BASE + g_levadj;
11759 } else {
11760 printf("%s: -l parameter requires a number, e.g. '-l3'\n"
11761 "\n", g_argv0);
11762 brief_help();
11763 print_end(-1);
11764 }
11765 } else {
11766 /* We have a bare "-l", or "--liou..." without the "--"; in either
11767 case this means we want to restrict to Liouvillian roots */
11768 set_restrict_alg(0);
11769 /* Enable exponential and logarithmic functions (but not Gamma or
11770 LambertW) */
11771 somesyms_set((symbol *) "eplEL", MAX_ELEN);
11772 /* To disallow x within an exponent, but still allow anything
11773 else in an exponent, we set g_restrict.subexpr to TYPE_TRAN
11774 which causes g_target to be tagged as transcendental. Then
11775 we restrict exponents and trigonometric arguments to elementary,
11776 allowing even something like e^(2^(1/phi)). This allows
11777 sqrt(2)^sqrt(2) to be found, but prevents finding the root of
11778 x^x=7. */
11779 g_restrict_subexpr = TYPE_TRAN;
11780 g_restrict_exponents = TYPE_ELEM;
11781 g_restrict_trig_args = TYPE_ELEM;
11782 if (pa_this_arg[2] == 'e') {
11783 /* They gave "-le"
11784 %%% This should instead set an epsilon as with
11785 --min-match-distance with a negative argument proportional
11786 to the ULP as measured by init.formats */
11787 g_exact_exit = B_TRUE;
11788 }
11789 }
11790
11791 } else if (strncmp(pa_this_arg, "-N", 2) == 0) {
11792 /* Not these symbols */
11793 NOS_options = B_TRUE;
11794 somesyms_set((symbol *) (pa_this_arg+2), 0); /* +2 skips "-N" */
11795
11796 } else if (strncmp(pa_this_arg, "-O", 2) == 0) {
11797 /* Once-only symbols */
11798 NOS_options = B_TRUE;
11799 somesyms_set((symbol *) (pa_this_arg+2), 1); /* +2 skips "-O" */
11800
11801 } else if ((strncmp(pa_this_arg, "-r", 2) == 0)
11802 || (strcmp(pa_this_arg, "--rational-subexpressions") == 0)) {
11803 /* Rational subexpressions */
11804 set_restrict_rat();
11805 if (pa_this_arg[2] == 'e') {
11806 /* They gave "-re" */
11807 g_exact_exit = B_TRUE;
11808 }
11809
11810 } else if (strncmp(pa_this_arg, "-S", 2) == 0) {
11811 /* Only these symbols */
11812 pa_this_arg += 2; /* skip the "-S" */
11813 if (*pa_this_arg == 0) {
11814 /* Without args, show the symbols in use and their definitions */
11815 g_show_ss = B_TRUE;
11816 } else {
11817 S_option = B_TRUE;
11818 NOS_options = B_TRUE;
11819 allsyms_set(0, 0);
11820 somesyms_set((symbol *) pa_this_arg, MAX_ELEN);
11821 }
11822
11823 } else if ((strcmp(pa_this_arg, "-x") == 0)
11824 || (strcmp(pa_this_arg, "--absolute-roots") == 0)) {
11825 /* Show values of x rather than "x = T + epsilon" */
11826 if (g_wide_output) {
11827 /* -x is incompatible with wide mode (which shows both types of x
11828 value output) */
11829 printf("Note: '%s' option with '--wide' is redundant.\n",
11830 pa_this_arg);
11831 } else {
11832 g_relative_x = B_FALSE;
11833 }
11834
11835 /* test for number must be last, because it might have a leading '-' */
11836 } else if (((pa_this_arg[0] >= '0') && (pa_this_arg[0] <= '9'))
11837 || (pa_this_arg[0] == '-') || (pa_this_arg[0] == '.')) {
11838 /* This would be the target number */
11839 nv = parse_target(pa_this_arg);
11840 if (nv == 1) {
11841 g_got_target = 1;
11842 } else {
11843 printf("%s: Unknown option '%s'\n\n", g_argv0, pa_this_arg);
11844 brief_help();
11845 print_end(-1);
11846 }
11847 } else {
11848 printf("%s: Unknown option '%s'\n\n", g_argv0, pa_this_arg);
11849 brief_help();
11850 print_end(-1);
11851 }
11852 }
11853 /* At this point pa_sp <= 0 and stk_nargs[pa_sp] == 0, so we're out of
11854 args */
11855
11856} /* End of parse.args */
11857
11858/* We use precise and sized datatypes (e.g. 16-bit integer), and
11859/ in some cases (old compilers) we need to define these with a custom
11860/ typedef. This function makes sure the definitions work the way we need
11861/ and complains if not. We can also tell the user which ifdef flag to
11862/ use when re-compiling. */
11863void validate_types(void)
11864{
11865#ifdef VT_TEST_CMP1
11866 {
11867 int i; unsigned u;
11868 i = 1; u = ((unsigned) -2);
11869 printf("i %08x u %08x\n", i, u);
11870 printf("cmp1 %s\n", (u<i) ? "T" : "nil");
11871 printf("cmp1 %s\n", (((signed)u)<i) ? "T" : "nil");
11872 printf("cmp1 %s\n", (u<((unsigned)i)) ? "T" : "nil");
11873 }
11874#endif
11875
11876 b001 flag1, flag2;
11877 flag1 = B_TRUE;
11878 flag2 = (1==1);
11879
11880 if (flag1 == flag2) {
11881 /* All is well */
11882 } else {
11883 /* Non-standard compiler and/or non-standard definition of B_TRUE: This
11884 / happens if "b001" is int, "B_TRUE" is 1, and "(1==1)" is __INT_MIN__,
11885 / or something similar. */
11886 printf("validate_types: B_TRUE does not match (1==1).\n");
11887 print_end(-1);
11888 }
11889
11890 if (sizeof(s16) != 2) {
11891 printf("validate_types: s16 is not 2 bytes (got %d).\n",
11892 (int) sizeof(s16));
11893 if (sizeof(short) == 2) {
11894 printf(
11895 " To fix this error, compile RIES with the flag -DSHORT_IS_S16\n");
11896 } else if (sizeof(int) == 2) {
11897 printf(
11898 " To fix this error, compile RIES with the flag -DINT_IS_S16\n");
11899 } else {
11900 printf(
11901 " (presently, sizeof(short)==%d and sizeof(int)==%d)\n",
11902 (int) sizeof(short), (int) sizeof(int));
11903 }
11904 print_end(-1);
11905 }
11906
11907 if (sizeof(s32) != 4) {
11908 printf("validate_types: s32 is not 4 bytes (got %d).\n",
11909 (int) sizeof(s32));
11910 if (sizeof(int) == 4) {
11911 printf(
11912 " To fix this error, compile RIES with the flag -DINT_IS_S32\n");
11913 } else if (sizeof(long) == 4) {
11914 printf(
11915 " To fix this error, compile RIES with the flag -DLONG_IS_S32\n");
11916 } else {
11917 printf(
11918 " (presently, sizeof(int)==%d and sizeof(long)==%d)\n",
11919 (int) sizeof(int), (int) sizeof(long));
11920 }
11921 print_end(-1);
11922 }
11923} /* End of validate.types */
11924
11925/* Try to make a guess as to whether a value is integer or rational.
11926 Due to the main purpose of the rational tags (filtering the types of
11927 arguments to transcendental functions) we only count it as rational
11928 if it's a half or quarter-integer.
11929 %%% tgs-manip: We could really go nuts and run a continued
11930 fraction series calculation, but that's second-guessing the user. I'd
11931 rather add a syntax allowing the user to explicitly give a fraction as
11932 the target number, and that's sort of counter to the purpose of RIES.
11933 Note that if the user knows what type the target is, she can use an
11934 option like -a or -c to specify it as such. */
11935ries_tgs guess_valtype(ries_val v)
11936{
11937 if (v == FLOOR(v)) {
11938 return TYPE_INT;
11939 } else if (FLOOR(v*4.0) == (v*4.0)) {
11940 /* Target is a half-integer or quarter-integer */
11941 return TYPE_RAT;
11942 }
11943 /* Set target class based on selected restriction, but not better than
11944 rational since we know it's not an integer. We are giving it
11945 the benefit of the doubt: in fact, *every* target value is
11946 rational because it is specified in terms of a finite number of
11947 decimal digits.
11948 If they set --rational-exponents (including the -a option),
11949 g_restrict_exponents will be set to TYPE_RAT and if this target
11950 type is also lower than RAT, we'll prohibit x in the exponent. */
11951 return TGMIN(TYPE_RAT, g_restrict_subexpr);
11952} /* End of guess.valtype */
11953
11954int main(int nargs, char *argv[])
11955{
11956 stats_count genf;
11957 ries_val tgt_to_print;
11958 stats_count lim_gentotal;
11959 stats_count lim_prune;
11960 int ml_going;
11961
11962#ifdef OLD_EXHAUSTION_TESTS
11963 s16 timeout;
11964 timeout = 0;
11965#endif
11966
11967 validate_types();
11968 ieee_paranoia();
11969 init_formats();
11970
11971 g_argv0 = argv[0]; /* Used in various sudden-death printf's */
11972
11973 init1();
11974
11975 g_got_target = 0;
11976
11977 /* parse arguments. Note that parse.args is a recursive algorithm with
11978 its own stack, executing nested loops for the --include option. */
11979 if (nargs > 1) {
11980 parse_args((size_t) nargs, argv);
11981 } else {
11982 printf("%s: Please specify a target number.\n"
11983 "\n", g_argv0);
11984 brief_help();
11985 print_end(1);
11986 }
11987
11988 /* init the evaluation system */
11989 init2();
11990
11991 /* Execute the '-S' command */
11992 if (g_show_ss) {
11993 show_symset();
11994 /* We exit because the main purpose of a bare -S is to learn the weights.
11995 However the user may have expected more, so we explain the necessary
11996 -S syntax. */
11997 printf("%s: %s", g_argv0,
11998"Exiting now (to do an equation search, omit '-S' or include\n"
11999" symbol names, for example: 'ries 3.14159 -S123456789+/')\n");
12000 exit(0);
12001 }
12002
12003 if (g_got_target) {
12004 g_targ_tags = guess_valtype(g_target);
12005 }
12006
12007 /* printf("valtype of pi is %s", tagname(tg_pi)); */
12008 if (g_restrict_subexpr > tg_pi) {
12009 tg_pi = TGMIN(TYPE_RAT, g_restrict_subexpr);
12010 }
12011 /* printf(" -> %s\n", tagname(tg_pi)); */
12012 if (g_restrict_subexpr > tg_phi) {
12013 tg_phi = TGMIN(TYPE_RAT, g_restrict_subexpr);
12014 }
12015 if (g_restrict_subexpr > tg_e) {
12016 tg_e = TGMIN(TYPE_RAT, g_restrict_subexpr);
12017 }
12018
12019 /* Execute the --eval-expression option */
12020 if (g_eval_expr && g_num_find_expr) {
12021 s16 i, err, sp, contains_x;
12022 ries_val x; ries_dif dx; ries_tgs tg;
12023 symbol * expr;
12024 exec_x = g_target;
12025 for(i=0; i<g_num_find_expr; i++) {
12026 expr = g_find_expr[i];
12027 printf("Evaluating postfix expression '%s'", expr);
12028 contains_x = (symstrsym(expr, 'x') != 0);
12029 if (contains_x) {
12030 printf(" with x=");
12031 spff(k_usable_digits, exec_x); /* printf(fmt_g_usa_fixed, exec_x); */
12032 }
12033 printf("\n");
12034 err = eval(expr, &x, &dx, &tg, &sp, 1); /* In main() */
12035 if (err) {
12036 printf("Error %d from eval: %s\n", err, err_string(err));
12037 } else if (sp > 0) {
12038 /* The other clients of eval() always have complete expressions,
12039 so eval() does not check for this error */
12040 printf("Error: incomplete expression (%d item(s) remain on stack)\n",
12041 sp);
12042 } else {
12043 printf("[%s] = ", expr);
12044 spfg(k_usable_digits, x); /* printf(fmt_g_usable, x); */
12045 printf("; d/dx = ");
12046 printf(fmt_g_diff, dx);
12047 printf(" %s", tagname(tg));
12048 printf(", complexity = {%d}\n", complexity(expr));
12049 }
12050 printf("\n");
12051 }
12052 exit(0);
12053 }
12054
12055 if (g_got_target == 0) {
12056 printf("%s: Please specify a target number.\n"
12057 "\n", g_argv0);
12058 brief_help();
12059 print_end(1);
12060 }
12061
12062 /* -i option is of no use when X isn't an integer, because X is a
12063 * subexpression of all LHS's; demote to rational.*/
12064 if (g_restrict_subexpr == TYPE_INT) {
12065 if (!(TAG_INT_P(g_targ_tags))) { /* tgs-manip */
12066 if (g_enable_output) {
12067 printf("ries: Replacing -i with -r because target isn't an integer.\n");
12068 }
12069 set_restrict_rat();
12070 /* g_exact_exit setting is still relevant */
12071 } else if (FABS(g_target) > rv_maxint) {
12072 if (g_enable_output) {
12073 printf("ries: Replacing -i with -r because target is too large.\n");
12074 }
12075 set_restrict_rat();
12076 /* g_exact_exit setting is still relevant */
12077 }
12078 }
12079
12080 /* Set or adjust target value and match distance cutoffs. */
12081 tgt_to_print = g_target; /* Save user-specified value for printing */
12082 if (g_match_all_digits) {
12083 if (g_mag_ulp > 0) {
12084 /* Tweak the target and set a max match distance */
12085 k_max_match_dist = g_mag_ulp * 0.5;
12086 if (g_target < 0) {
12087 g_target -= k_max_match_dist;
12088 } else {
12089 g_target += k_max_match_dist;
12090 }
12091 /* In the case where they gave an integer or rational with
12092 --match-all-digits, 1/2 of the ULP is added to the target
12093 which is therefore rational. */
12094 if (g_targ_tags == TYPE_INT) { g_targ_tags = TYPE_RAT; } /* tgs-manip */
12095
12096 /* For --match-all-digits to make sense the roots should be displayed
12097 as absolute numbers, not "x = T + epsilon" */
12098 if (g_wide_output == B_FALSE) {
12099 g_relative_x = B_FALSE;
12100 }
12101 /* printf("Setting target: %g and k_max_match.dist %g\n",
12102 g_target, k_max_match_dist); */
12103 } else {
12104 /* %%% We could handle this as "--max-match-distance 0", but it's
12105 safer to assume we don't know the exact value of the last digit(s)
12106 and therefore cannot match them. */
12107 printf(
12108 "Ignoring --match-all-digits option because I could not determine\n"
12109 "the magnitude of the ULP (unit in the last place).\n"
12110 );
12111 }
12112 }
12113
12114 if (k_derivative_margin > 0) {
12115 /* They selected a specific initial k_vanished.dx */
12116 k_vanished_dx = k_derivative_margin;
12117 } else if (fabs((ries_dif)g_target) * k_vanished_dx > 0.1) {
12118 k_vanished_dx = 0.1 / fabs((ries_dif)g_target);
12119 printf("Auto-setting --derivative-margin %g\n", k_vanished_dx);
12120 } else if (fabs((ries_dif)g_target) < 1.0e-8) {
12121 k_vanished_dx = 0.1 * fabs((ries_dif)g_target);
12122 printf("Auto-setting --derivative-margin %g\n", k_vanished_dx);
12123 }
12124 if (debug_z) {
12125 printf("fabs(g_target) == %g; k_vanished_dx == %g;\n",
12126 fabs((ries_dif)g_target), k_vanished_dx);
12127 printf("fabs(g_target) * k_vanished_dx == %g\n",
12128 fabs((ries_dif)g_target) * k_vanished_dx);
12129 }
12130
12131 /* If k_vanished.dx changed, make k_prune.deriv agree */
12132 k_prune_deriv = k_vanished_dx / 1.0e4;
12133 p_ovr = fabs((ries_dif)g_target) / k_prune_deriv;
12134 n_ovr = - p_ovr;
12135 if (debug_z) {
12136 printf("k_prune_deriv == %g; p_ovr == %g\n", k_prune_deriv, p_ovr);
12137 }
12138
12139 if (k_vanished_dx >= 1.0/FABS(g_target)) {
12140 printf(
12141"%s: With this --derivative-margin option (%g) and\n"
12142" target value (%g), I cannot compute any expressions. Either\n"
12143" use a smaller target value, or a derivative margin below %g\n\n",
12144 g_argv0, k_vanished_dx, dbl(g_target), 1.0/fabs((ries_dif)g_target));
12145 print_end(-1);
12146 }
12147 if (FABS((ries_dif)g_target) / k_vanished_dx >= 1.0e15) {
12148 if (sym_attrs['x'].sa_alwd > 1) {
12149 if (k_derivative_margin > 0) {
12150 printf(
12151"WARNING: Your --derivative-margin option (%g)\n"
12152" is so small that RIES might report tautologies like x/x = 1. To avoid\n"
12153" this warning, use the option -Ox or give a target value smaller than\n"
12154" %g.\n\n",
12155 k_derivative_margin, k_biggest_safe_target);
12156 } else {
12157 printf(
12158"WARNING: Your target value is so large that RIES might report tautologies\n"
12159" like x/(x/3) = 3. To avoid this warning, use the option -Ox or give a\n"
12160" target value smaller than %g.\n\n",
12161 k_biggest_safe_target);
12162 }
12163 }
12164 }
12165
12166 if (g_min_matchsize < 0.0) {
12167 /* Variable minimum match threshold */
12168 g_min_matchsize = fabs((ries_dif)g_target * (-g_min_matchsize));
12169 }
12170
12171 if (k_max_match_dist >= 0) {
12172 /* They have set a fixed starting match threshold */
12173 g_init_match_dist = k_max_match_dist;
12174 } else {
12175 /* Variable starting match threshold */
12176 g_init_match_dist = fabs((ries_dif)g_target * (-k_max_match_dist));
12177 }
12178 best_match = g_init_match_dist;
12179 if (debug_q) {
12180 printf("Initial match threshold = %g\n", dbl(best_match));
12181 }
12182 /* Adjust k_min_best.match to accomodate precision and large targets.
12183 %%% We do this for large-magnitude targets and for targets close to 0.
12184 I still need to look more closely at how I handle SIG_LOSS errors
12185 and how that affects operation when the target is close to zero. */
12186 if ((FABS(g_target) > 1.0) || (FABS(g_target) < 0.25)) {
12187 k_min_best_match = fabs((ries_dif)g_target) * 8.0 * k_precision_ulp;
12188 if (debug_z) {
12189 if (FABS(g_target) > 1.0) {
12190 printf("Large target, setting kmbm=%g\n", k_min_best_match);
12191 } else {
12192 printf("Small target, setting kmbm=%g\n", k_min_best_match);
12193 }
12194 }
12195 }
12196 exec_x = g_target;
12197
12198 if (g_anagram != 0) {
12199 g_one_sided = B_TRUE;
12200 }
12201
12202 /* --------------------------------------------------------------------------
12203 Finished adjusting parameters; start algorithm
12204 -------------------------------------------------------------------------- */
12205
12206 if (g_enable_output) {
12207 char fmt1[FMT_STR_SIZE];
12208 printf("\n");
12209 printf(" Your target value: T = ");
12210 spff(k_usable_digits, tgt_to_print); /* printf(fmt_g_usa_fixed, tgt_to_print) */
12211 /* If robustness were not important we could use the "%*" printf
12212 extension to get the variable width */
12213 snprintf(fmt1, FMT_STR_SIZE, "%s%d%s", " %", 44 - k_usable_digits, "s"); /* " %27s" */
12214 printf(fmt1, "mrob.com/ries");
12215 printf("%s", "\n\n");
12216 }
12217
12218 /* printing symbol weight limits for debugging */
12219 if (debug_z) {
12220 printf("Symbol weight ranges:\n");
12221 printf(" seft num minw maxw\n");
12222 printf(" %c %3d %3d %3d\n", 'a', n_asym, g_a_minw, g_a_maxw);
12223 printf(" %c %3d %3d %3d\n", 'b', n_bsym, g_b_minw, g_b_maxw);
12224 printf(" %c %3d %3d %3d\n", 'c', n_csym, g_c_minw, g_c_maxw);
12225 }
12226
12227 /* calculate search cutoff. This number is the total number of
12228 * expressions generated. Note that the total number of possible
12229 * combinations between LHS and RHS is much more: If N expressions
12230 * are generated and equally divided between LHS and RHS, the total
12231 * number of combinations is N^2/4. Thus, we get 4 times as many
12232 * combinations each time we double this number.
12233 * The user interface says that each level will produce a 10-times
12234 * greater search. This means checking 10 times as many combinations.
12235 * however, as the number of combinations rises they also get more
12236 * spread out, because more very large and very small numbers are
12237 * getting generated. Because of this spreading out, LHS and RHS
12238 * expressions become slightly less likely to be near each other as
12239 * the number of combinations goes up. Therefore, in order to get 10
12240 * times more "relevant" combinations, we multiply by factors of 4,
12241 * since 4^2 is 16, somewhat more than 10. */
12242 lim_gentotal = 2000.0;
12243 if (tlevel >= -2.0) {
12244 lim_gentotal *= pow(4.0, tlevel);
12245 }
12246 lim_prune = lim_gentotal * 15.0;
12247 gen_total = 0;
12248 if (debug_y) {
12249 printf("Will stop after generating searchmax=%g expressions\n",
12250 lim_gentotal);
12251 }
12252
12253#ifdef RIES_USE_SA_M64
12254 /* Test of new Lambert W function in msal_math64.c */
12255 if (debug_z) {
12256# ifdef RIES_VAL_LDBL
12257 msal_test_lambertl();
12258# else
12259 msal_test_lambert();
12260# endif
12261 msal_test_gamma();
12262 msal_test_spfg();
12263 }
12264#endif
12265
12266 /* generate and print solutions */
12267 lmin = rmin = 1;
12268 lmax = rmax = PASS_GRAN;
12269 rhs_gen = lhs_gen = 0;
12270 rhs_insert = lhs_insert = 0;
12271 rhs_prune = lhs_prune = 0;
12272 got_exact = B_FALSE;
12273 g_num_matches = 0;
12274 ml_going = 1;
12275 while (ml_going) {
12276 /* We increase the complexity limit of whichever side has generated
12277 the least number of expressions so far. This is to ensure that we
12278 stay near the optimal point where the search time is O(sqrt(K^N)).
12279 If we let one side outnumber the other by a lot, the search gets
12280 to be more like O(K^N), and we don't want that (-:
12281
12282 Note that we are going by the actual number of LHS and RHS items
12283 in the database, rather than maintaining an equal complexity limit
12284 for both types of expressions. This is to adapt gracefully to
12285 changes in the symbol
12286 set, which of course can be specified on the command line. For
12287 example, if they significantly limit the number of constants,
12288 the LHS will grow at a faster rate than the RHS because its one
12289 additional type-a symbol ('x') becomes a significant factor in how
12290 many expressions there are of each complexity.
12291
12292 Since LHS and RHS are stored in the same struct type, there is no
12293 memory savings from storing fewer LHS's, however there might be
12294 a bit of speed cost from evaluating the derivatives.
12295 storing them. Some kind of benchmarking would be in order.
12296
12297 For the --one.sided option, the main test is altered so that
12298 it inserts x as the sole LHS expression and then performs RHS
12299 passes from then on.
12300 */
12301
12302 g_ne = 0; insert_count = 0; prune_count = 0;
12303 if (
12304 (g_one_sided && (lhs_insert >= 1)) /* We're in RHS-only mode and
12305 we have our 'x' */
12306 || (lhs_insert > rhs_insert)) /* Or normal mode and LHS
12307 outnumbers RHS */
12308 {
12309 rmin = (s16)(rmin + PASS_GRAN);
12310 rmax = (s16)(rmax + PASS_GRAN);
12311
12312 /* Generate RHS expressions */
12313 g_dbg_side = DBG_RHS;
12314 genf = gen_forms(rmin, rmax, 0,
12315 g_a_minw, g_a_maxw, g_b_minw, g_b_maxw, g_c_minw, g_c_maxw);
12316 if (debug_y) {
12317 printf("finished RHS from {%d} to {%d}: %g forms expanded, %g expressions.\n",
12318 rmin, rmax, genf, g_ne);
12319 }
12320 rhs_gen += g_ne;
12321 rhs_insert += insert_count;
12322 rhs_prune += prune_count;
12323 } else {
12324 lmin = (s16)(lmin + PASS_GRAN);
12325 lmax = (s16)(lmax + PASS_GRAN);
12326
12327 /* Generate LHS expressions */
12328 g_dbg_side = DBG_LHS;
12329 genf = gen_forms(lmin, lmax, 1,
12330 g_a_minw, g_a_maxw, g_b_minw, g_b_maxw, g_c_minw, g_c_maxw);
12331 if (debug_y) {
12332 printf("finished LHS from {%d} to {%d}: %g forms expanded, %g expressions.\n",
12333 lmin, lmax, genf, g_ne);
12334 printf("\n");
12335 }
12336 lhs_gen += g_ne;
12337 lhs_insert += insert_count;
12338 lhs_prune += prune_count;
12339 }
12340 gen_total += g_ne;
12341
12342#ifdef OLD_EXHAUSTION_TESTS
12343 /* Test the number of new expressions found. Reset the timeout if we
12344 found new expressions. If we go too many passes and find nothing, the
12345 search will terminate.
12346 This test prevents an infinite loop in the case where the
12347 searchmax is so big (or the symbolset so small) that all possible
12348 expressions of size MAX_ELEN are generated becore searchmax is
12349 reached. (If this actually happens, it probably means MAX_ELEN should
12350 be increased.) */
12351 if (g_ne > 0) {
12352 timeout = 0;
12353 } else {
12354 timeout++;
12355 }
12356 /* %%% with -i and/or -S it's not very reliable. Instead of timing
12357 * out we should use an explicit test: is complexity minimum
12358 * larger than max complexity possible in length MAX_ELEN? */
12359 if (timeout > 40) { }
12360#endif
12361
12362 /* Detect exhaustion */
12363 if ((lmax > g_exhaust_cpx)
12364 && (g_one_sided || (rmax > g_exhaust_cpx)))
12365 {
12366 /* If no actual results have been given, report some reasons why this
12367 might happen. Otherwise, we'll assume they know what they're doing.
12368 For example, "ries 17 '-S+*-/' --numeric-anagram 4444 -Ox" prints
12369 a single result and then triggers this code before the default
12370 searchlevel is complete. */
12371 if (g_num_matches == 0) {
12372 printf(
12373 "exhaustion timeout (complexity LHS {%d}, RHS {%d}). Possible causes:\n"
12374 " MAX_ELEN %d too small\n",
12375 lmax, rmax, MAX_ELEN);
12376
12377 if (NOS_options) {
12378 printf(" too many symbols excluded via -N, -O or -S\n");
12379 }
12380 if (g_anagram) {
12381 printf(" --numeric-anagram too restrictive\n");
12382 }
12383 if (k_derivative_margin == 0) {
12384 printf(" target too big or small for k_vanished_dx (use --derivative-margin)\n");
12385 }
12386 g_reported_exhaustion = B_TRUE;
12387 }
12388 gen_total = lim_gentotal;
12389 }
12390
12391 if (debug_y || debug_0) {
12392 printf("gen_total %g (lhs %ld rhs %ld) searchmax %g gnm %ld\n",
12393 gen_total, lhs_insert, rhs_insert, lim_gentotal, (long) g_num_matches);
12394 bt_stats();
12395 }
12396
12397 /* If we have spent more than a couple seconds and still not reported
12398 a match, it's probably because they made really stringent demands,
12399 such as a very small k_max.match_dist value. Let them know that this
12400 might take a while... */
12401 if (g_num_matches == 0) {
12402 time_flt tsec = gettime();
12403 if (debug_y
12404 || ((tsec > 2.0) && g_allow_slow_message)) {
12405 printf(" Still searching: %11s expr and %.3f sec so far... \r",
12406 pf_intfloat_wid(gen_total, 11), tsec);
12407 fflush(stdout);
12408 }
12409 }
12410
12411 /* The main loop exits based on how much work we've done, as measured
12412 by counting how many expressions were generated (or pruned) rather
12413 than just looking at how high the complexity score has gotten.
12414 We measure how much work we've done in two different ways: number
12415 of "dead-ends" that were discarded (pruned), and number of valid
12416 complete expressions (not necessarily with distinct values). Having
12417 these two different exit conditions is important so that a "level N"
12418 search takes about the same amount of time in normal unrestricted
12419 search (bi-directional, full symbolset) and in uni-directional search
12420 modes (e.g. for --numeric-anagram). */
12421 if ((lhs_prune+rhs_prune) >= lim_prune) {
12422 ml_going = 0;
12423 }
12424 if (gen_total >= lim_gentotal) {
12425 ml_going = 0;
12426 }
12427 } /* End of if(ml_going) */
12428
12429 if (debug_y) {
12430 printf("Level %.g search complete (gen_total exceeded lim_gentotal).\n",
12431 g_levadj);
12432 }
12433
12434 /* Given appropriate advice about how to get more results */
12435 if (g_enable_output) {
12436 if (g_reported_exhaustion) {
12437 /* If the exhaustion timeout error was reported, increasing the
12438 searchlevel will not help. */
12439 } else if (g_num_matches == 0) {
12440 printf("No solution was found (try using -l%d",
12441 ((int) floor(g_levadj+1.0)));
12442 if (g_init_match_dist < (0.001 * g_target)) {
12443 printf(" or a larger --max-match-distance");
12444 }
12445 printf("). \n");
12446 } else if (g_exact_exit) {
12447 printf(
12448 " No 'exact' solution was found (try using -l%d).\n",
12449 ((int) floor(g_levadj+1.0)));
12450 } else {
12451 printf(" (for more results, use the option '-l%d')\n",
12452 ((int) floor(g_levadj+1.0)));
12453 }
12454 }
12455
12456 print_end(0);
12457
12458 return 0;
12459}
12460
12461/*
12462 ries.c
12463 RIES -- Find Algebraic Equations, Given Their Solution
12464 Copyright (C) 2000-2016 Robert P. Munafo
12465
12466 See copyright notice at beginning of this file.
12467 */