-
Notifications
You must be signed in to change notification settings - Fork 266
/
readme.txt
6238 lines (4843 loc) · 235 KB
/
readme.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
C++ Mathematical Expression Toolkit Library Documentation
Section 00 - Introduction
Section 01 - Capabilities
Section 02 - Example Expressions
Section 03 - Copyright Notice
Section 04 - Downloads & Updates
Section 05 - Installation
Section 06 - Compilation
Section 07 - Compiler Compatibility
Section 08 - Built-In Operations & Functions
Section 09 - Fundamental Types
Section 10 - Components
Section 11 - Compilation Options
Section 12 - Expression Structures
Section 13 - Variable, Vector & String Definition
Section 14 - Vector Processing
Section 15 - User Defined Functions
Section 16 - Expression Dependents
Section 17 - Hierarchies Of Symbol Tables
Section 18 - Unknown Unknowns
Section 19 - Enabling & Disabling Features
Section 20 - Expression Return Values
Section 21 - Compilation Errors
Section 22 - Runtime Library Packages
Section 23 - Helpers & Utils
Section 24 - Runtime Checks
Section 25 - Benchmarking
Section 26 - Exprtk Notes
Section 27 - Simple Exprtk Example
Section 28 - Build Options
Section 29 - Files
Section 30 - Language Structure
[SECTION 00 - INTRODUCTION]
The C++ Mathematical Expression Toolkit Library (ExprTk) is a simple
to use, easy to integrate and extremely efficient run-time
mathematical expression parsing and evaluation engine. The parsing
engine supports numerous forms of functional and logic processing
semantics and is easily extensible.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 01 - CAPABILITIES]
The ExprTk expression evaluator supports the following fundamental
arithmetic operations, functions and processes:
(00) Types: Scalar, Vector, String
(01) Basic operators: +, -, *, /, %, ^
(02) Assignment: :=, +=, -=, *=, /=, %=
(03) Equalities &
Inequalities: =, ==, <>, !=, <, <=, >, >=
(04) Logic operators: and, mand, mor, nand, nor, not, or, shl, shr,
xnor, xor, true, false
(05) Functions: abs, avg, ceil, clamp, equal, erf, erfc, exp,
expm1, floor, frac, log, log10, log1p, log2,
logn, max, min, mul, ncdf, not_equal, root,
round, roundn, sgn, sqrt, sum, swap, trunc
(06) Trigonometry: acos, acosh, asin, asinh, atan, atanh, atan2,
cos, cosh, cot, csc, sec, sin, sinc, sinh,
tan, tanh, hypot, rad2deg, deg2grad, deg2rad,
grad2deg
(07) Control
structures: if-then-else, ternary conditional, switch-case,
return-statement
(08) Loop statements: while, for, repeat-until, break, continue
(09) String
processing: in, like, ilike, concatenation
(10) Optimisations: constant-folding, simple strength reduction and
dead code elimination
(11) Runtime checks: vector bounds, string bounds, loop iteration,
execution-time bounds and compilation process
checkpointing, assert statements
(12) Calculus: numerical integration and differentiation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 02 - EXAMPLE EXPRESSIONS]
The following is a short listing of infix format based mathematical
expressions that can be parsed and evaluated using the ExprTk library.
(01) sqrt(1 - (3 / x^2))
(02) clamp(-1, sin(2 * pi * x) + cos(y / 2 * pi), +1)
(03) sin(2.34e-3 * x)
(04) if(((x[2] + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)
(05) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)
(06) ({1/1}*[1/2]+(1/3))-{1/4}^[1/5]+(1/6)-({1/7}+[1/8]*(1/9))
(07) a * exp(2.2 / 3.3 * t) + c
(08) z := x + sin(2.567 * pi / y)
(09) u := 2.123 * {pi * z} / (w := x + cos(y / pi))
(10) 2x + 3y + 4z + 5w == 2 * x + 3 * y + 4 * z + 5 * w
(11) 3(x + y) / 2.9 + 1.234e+12 == 3 * (x + y) / 2.9 + 1.234e+12
(12) (x + y)3.3 + 1 / 4.5 == [x + y] * 3.3 + 1 / 4.5
(13) (x + y[i])z + 1.1 / 2.7 == (x + y[i]) * z + 1.1 / 2.7
(14) (sin(x / pi) cos(2y) + 1) == (sin(x / pi) * cos(2 * y) + 1)
(15) 75x^17 + 25.1x^5 - 35x^4 - 15.2x^3 + 40x^2 - 15.3x + 1
(16) (avg(x,y) <= x + y ? x - y : x * y) + 2.345 * pi / x
(17) while (x <= 100) { x -= 1; }
(18) x <= 'abc123' and (y in 'AString') or ('1x2y3z' != z)
(19) ((x + 'abc') like '*123*') or ('a123b' ilike y)
(20) sgn(+1.2^3.4z / -5.6y) <= {-7.8^9 / -10.11x }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 03 - COPYRIGHT NOTICE]
Free use of the C++ Mathematical Expression Toolkit Library is
permitted under the guidelines and in accordance with the most current
version of the MIT License.
(1) https://www.opensource.org/licenses/MIT
(2) SPDX-License-Identifier: MIT
(3) SPDX-FileCopyrightText : Copyright (C) 1999-2024 Arash Partow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 04 - DOWNLOADS & UPDATES]
The most recent version of the C++ Mathematical Expression Toolkit
Library including all updates and tests can be found at the following
locations:
(1) Download: https://www.partow.net/programming/exprtk/index.html
(2) Mirror Repository: https://github.com/ArashPartow/exprtk
https://github.com/ArashPartow/exprtk-extras
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 05 - INSTALLATION]
The header file exprtk.hpp should be placed in a project or system
include path (e.g: /usr/include/).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 06 - COMPILATION]
The ExprTk package contains the ExprTk header, a set of simple
examples and a benchmark and unit test suite. The following is a list
of commands to build the various components:
(a) For a complete build: make clean all
(b) For a PGO build: make clean pgo
(c) To strip executables: make strip_bin
(d) Execute valgrind check: make valgrind_check
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 07 - COMPILER COMPATIBILITY]
ExprTk has been built error and warning free using the following set
of C++ compilers:
(*) GNU Compiler Collection (3.5+)
(*) Clang/LLVM (1.1+)
(*) Microsoft Visual Studio C++ Compiler (7.1+)
(*) Intel C++ Compiler (8.x+)
(*) AMD Optimizing C++ Compiler (1.2+)
(*) Nvidia C++ Compiler (19.x+)
(*) PGI C++ (10.x+)
(*) Circle C++ (circa: b81c37d2bb227c)
(*) IBM XL C/C++ (9.x+)
(*) C++ Builder (XE4+)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 08 - BUILT-IN OPERATIONS & FUNCTIONS]
(0) Arithmetic & Assignment Operators
+----------+---------------------------------------------------------+
| OPERATOR | DEFINITION |
+----------+---------------------------------------------------------+
| + | Addition between x and y. (eg: x + y) |
+----------+---------------------------------------------------------+
| - | Subtraction between x and y. (eg: x - y) |
+----------+---------------------------------------------------------+
| * | Multiplication between x and y. (eg: x * y) |
+----------+---------------------------------------------------------+
| / | Division between x and y. (eg: x / y) |
+----------+---------------------------------------------------------+
| % | Modulus of x with respect to y. (eg: x % y) |
+----------+---------------------------------------------------------+
| ^ | x to the power of y. (eg: x ^ y) |
+----------+---------------------------------------------------------+
| := | Assign the value of x to y. Where y is either a variable|
| | or vector type. (eg: y := x) |
+----------+---------------------------------------------------------+
| += | Increment x by the value of the expression on the right |
| | hand side. Where x is either a variable or vector type. |
| | (eg: x += abs(y - z)) |
+----------+---------------------------------------------------------+
| -= | Decrement x by the value of the expression on the right |
| | hand side. Where x is either a variable or vector type. |
| | (eg: x[i] -= abs(y + z)) |
+----------+---------------------------------------------------------+
| *= | Assign the multiplication of x by the value of the |
| | expression on the righthand side to x. Where x is either|
| | a variable or vector type. |
| | (eg: x *= abs(y / z)) |
+----------+---------------------------------------------------------+
| /= | Assign the division of x by the value of the expression |
| | on the right-hand side to x. Where x is either a |
| | variable or vector type. (eg: x[i + j] /= abs(y * z)) |
+----------+---------------------------------------------------------+
| %= | Assign x modulo the value of the expression on the right|
| | hand side to x. Where x is either a variable or vector |
| | type. (eg: x[2] %= y ^ 2) |
+----------+---------------------------------------------------------+
(1) Equalities & Inequalities
+----------+---------------------------------------------------------+
| OPERATOR | DEFINITION |
+----------+---------------------------------------------------------+
| == or = | True only if x is strictly equal to y. (eg: x == y) |
+----------+---------------------------------------------------------+
| <> or != | True only if x does not equal y. (eg: x <> y or x != y) |
+----------+---------------------------------------------------------+
| < | True only if x is less than y. (eg: x < y) |
+----------+---------------------------------------------------------+
| <= | True only if x is less than or equal to y. (eg: x <= y) |
+----------+---------------------------------------------------------+
| > | True only if x is greater than y. (eg: x > y) |
+----------+---------------------------------------------------------+
| >= | True only if x greater than or equal to y. (eg: x >= y) |
+----------+---------------------------------------------------------+
(2) Boolean Operations
+----------+---------------------------------------------------------+
| OPERATOR | DEFINITION |
+----------+---------------------------------------------------------+
| true | True state or any value other than zero (typically 1). |
+----------+---------------------------------------------------------+
| false | False state, value of exactly zero. |
+----------+---------------------------------------------------------+
| and | Logical AND, True only if x and y are both true. |
| | (eg: x and y) |
+----------+---------------------------------------------------------+
| mand | Multi-input logical AND, True only if all inputs are |
| | true. Left to right short-circuiting of expressions. |
| | (eg: mand(x > y, z < w, u or v, w and x)) |
+----------+---------------------------------------------------------+
| mor | Multi-input logical OR, True if at least one of the |
| | inputs are true. Left to right short-circuiting of |
| | expressions. (eg: mor(x > y, z < w, u or v, w and x)) |
+----------+---------------------------------------------------------+
| nand | Logical NAND, True only if either x or y is false. |
| | (eg: x nand y) |
+----------+---------------------------------------------------------+
| nor | Logical NOR, True only if the result of x or y is false |
| | (eg: x nor y) |
+----------+---------------------------------------------------------+
| not | Logical NOT, Negate the logical sense of the input. |
| | (eg: not(x and y) == x nand y) |
+----------+---------------------------------------------------------+
| or | Logical OR, True if either x or y is true. (eg: x or y) |
+----------+---------------------------------------------------------+
| xor | Logical XOR, True only if the logical states of x and y |
| | differ. (eg: x xor y) |
+----------+---------------------------------------------------------+
| xnor | Logical XNOR, True iff the biconditional of x and y is |
| | satisfied. (eg: x xnor y) |
+----------+---------------------------------------------------------+
| & | Similar to AND but with left to right expression short |
| | circuiting optimisation. (eg: (x & y) == (y and x)) |
+----------+---------------------------------------------------------+
| | | Similar to OR but with left to right expression short |
| | circuiting optimisation. (eg: (x | y) == (y or x)) |
+----------+---------------------------------------------------------+
(3) General Purpose Functions
+----------+---------------------------------------------------------+
| FUNCTION | DEFINITION |
+----------+---------------------------------------------------------+
| abs | Absolute value of x. (eg: abs(x)) |
+----------+---------------------------------------------------------+
| avg | Average of all the inputs. |
| | (eg: avg(x,y,z,w,u,v) == (x + y + z + w + u + v) / 6) |
+----------+---------------------------------------------------------+
| ceil | Smallest integer that is greater than or equal to x. |
+----------+---------------------------------------------------------+
| clamp | Clamp x in range between r0 and r1, where r0 < r1. |
| | (eg: clamp(r0,x,r1)) |
+----------+---------------------------------------------------------+
| equal | Equality test between x and y using normalised epsilon |
+----------+---------------------------------------------------------+
| erf | Error function of x. (eg: erf(x)) |
+----------+---------------------------------------------------------+
| erfc | Complimentary error function of x. (eg: erfc(x)) |
+----------+---------------------------------------------------------+
| exp | e to the power of x. (eg: exp(x)) |
+----------+---------------------------------------------------------+
| expm1 | e to the power of x minus 1, where x is very small. |
| | (eg: expm1(x)) |
+----------+---------------------------------------------------------+
| floor | Largest integer that is less than or equal to x. |
| | (eg: floor(x)) |
+----------+---------------------------------------------------------+
| frac | Fractional portion of x. (eg: frac(x)) |
+----------+---------------------------------------------------------+
| hypot | Hypotenuse of x and y (eg: hypot(x,y) = sqrt(x*x + y*y))|
+----------+---------------------------------------------------------+
| iclamp | Inverse-clamp x outside of the range r0 and r1. Where |
| | r0 < r1. If x is within the range it will snap to the |
| | closest bound. (eg: iclamp(r0,x,r1) |
+----------+---------------------------------------------------------+
| inrange | In-range returns 'true' when x is within the range r0 |
| | and r1. Where r0 < r1. (eg: inrange(r0,x,r1) |
+----------+---------------------------------------------------------+
| log | Natural logarithm of x. (eg: log(x)) |
+----------+---------------------------------------------------------+
| log10 | Base 10 logarithm of x. (eg: log10(x)) |
+----------+---------------------------------------------------------+
| log1p | Natural logarithm of 1 + x, where x is very small. |
| | (eg: log1p(x)) |
+----------+---------------------------------------------------------+
| log2 | Base 2 logarithm of x. (eg: log2(x)) |
+----------+---------------------------------------------------------+
| logn | Base N logarithm of x. where n is a positive integer. |
| | (eg: logn(x,8)) |
+----------+---------------------------------------------------------+
| max | Largest value of all the inputs. (eg: max(x,y,z,w,u,v)) |
+----------+---------------------------------------------------------+
| min | Smallest value of all the inputs. (eg: min(x,y,z,w,u)) |
+----------+---------------------------------------------------------+
| mul | Product of all the inputs. |
| | (eg: mul(x,y,z,w,u,v,t) == (x * y * z * w * u * v * t)) |
+----------+---------------------------------------------------------+
| ncdf | Normal cumulative distribution function. (eg: ncdf(x)) |
+----------+---------------------------------------------------------+
| not_equal| Not-equal test between x and y using normalised epsilon |
+----------+---------------------------------------------------------+
| pow | x to the power of y. (eg: pow(x,y) == x ^ y) |
+----------+---------------------------------------------------------+
| root | Nth-Root of x. where n is a positive integer. |
| | (eg: root(x,3) == x^(1/3)) |
+----------+---------------------------------------------------------+
| round | Round x to the nearest integer. (eg: round(x)) |
+----------+---------------------------------------------------------+
| roundn | Round x to n decimal places (eg: roundn(x,3)) |
| | where n > 0 and is an integer. |
| | (eg: roundn(1.2345678,4) == 1.2346) |
+----------+---------------------------------------------------------+
| sgn | Sign of x, -1 where x < 0, +1 where x > 0, else zero. |
| | (eg: sgn(x)) |
+----------+---------------------------------------------------------+
| sqrt | Square root of x, where x >= 0. (eg: sqrt(x)) |
+----------+---------------------------------------------------------+
| sum | Sum of all the inputs. |
| | (eg: sum(x,y,z,w,u,v,t) == (x + y + z + w + u + v + t)) |
+----------+---------------------------------------------------------+
| swap | Swap the values of the variables x and y and return the |
| <=> | current value of y. (eg: swap(x,y) or x <=> y) |
+----------+---------------------------------------------------------+
| trunc | Integer portion of x. (eg: trunc(x)) |
+----------+---------------------------------------------------------+
(4) Trigonometry Functions
+----------+---------------------------------------------------------+
| FUNCTION | DEFINITION |
+----------+---------------------------------------------------------+
| acos | Arc cosine of x expressed in radians. Interval [-1,+1] |
| | (eg: acos(x)) |
+----------+---------------------------------------------------------+
| acosh | Inverse hyperbolic cosine of x expressed in radians. |
| | (eg: acosh(x)) |
+----------+---------------------------------------------------------+
| asin | Arc sine of x expressed in radians. Interval [-1,+1] |
| | (eg: asin(x)) |
+----------+---------------------------------------------------------+
| asinh | Inverse hyperbolic sine of x expressed in radians. |
| | (eg: asinh(x)) |
+----------+---------------------------------------------------------+
| atan | Arc tangent of x expressed in radians. Interval [-1,+1] |
| | (eg: atan(x)) |
+----------+---------------------------------------------------------+
| atan2 | Arc tangent of (x / y) expressed in radians. [-pi,+pi] |
| | eg: atan2(x,y) |
+----------+---------------------------------------------------------+
| atanh | Inverse hyperbolic tangent of x expressed in radians. |
| | (eg: atanh(x)) |
+----------+---------------------------------------------------------+
| cos | Cosine of x. (eg: cos(x)) |
+----------+---------------------------------------------------------+
| cosh | Hyperbolic cosine of x. (eg: cosh(x)) |
+----------+---------------------------------------------------------+
| cot | Cotangent of x. (eg: cot(x)) |
+----------+---------------------------------------------------------+
| csc | Cosecant of x. (eg: csc(x)) |
+----------+---------------------------------------------------------+
| sec | Secant of x. (eg: sec(x)) |
+----------+---------------------------------------------------------+
| sin | Sine of x. (eg: sin(x)) |
+----------+---------------------------------------------------------+
| sinc | Sine cardinal of x. (eg: sinc(x)) |
+----------+---------------------------------------------------------+
| sinh | Hyperbolic sine of x. (eg: sinh(x)) |
+----------+---------------------------------------------------------+
| tan | Tangent of x. (eg: tan(x)) |
+----------+---------------------------------------------------------+
| tanh | Hyperbolic tangent of x. (eg: tanh(x)) |
+----------+---------------------------------------------------------+
| deg2rad | Convert x from degrees to radians. (eg: deg2rad(x)) |
+----------+---------------------------------------------------------+
| deg2grad | Convert x from degrees to gradians. (eg: deg2grad(x)) |
+----------+---------------------------------------------------------+
| rad2deg | Convert x from radians to degrees. (eg: rad2deg(x)) |
+----------+---------------------------------------------------------+
| grad2deg | Convert x from gradians to degrees. (eg: grad2deg(x)) |
+----------+---------------------------------------------------------+
(5) String Processing
+----------+---------------------------------------------------------+
| FUNCTION | DEFINITION |
+----------+---------------------------------------------------------+
| = , == | All common equality/inequality operators are applicable |
| !=, <> | to strings and are applied in a case sensitive manner. |
| <=, >= | In the following example x, y and z are of type string. |
| < , > | (eg: not((x <= 'AbC') and ('1x2y3z' <> y)) or (z == x) |
+----------+---------------------------------------------------------+
| in | True only if x is a substring of y. |
| | (eg: x in y or 'abc' in 'abcdefgh') |
+----------+---------------------------------------------------------+
| like | True only if the string x matches the pattern y. |
| | Available wildcard characters are '*' and '?' denoting |
| | zero or more and zero or one matches respectively. |
| | (eg: x like y or 'abcdefgh' like 'a?d*h') |
+----------+---------------------------------------------------------+
| ilike | True only if the string x matches the pattern y in a |
| | case insensitive manner. Available wildcard characters |
| | are '*' and '?' denoting zero or more and zero or one |
| | matches respectively. |
| | (eg: x ilike y or 'a1B2c3D4e5F6g7H' ilike 'a?d*h') |
+----------+---------------------------------------------------------+
| [r0:r1] | The closed interval[r0,r1] of the specified string. |
| | eg: Given a string x with a value of 'abcdefgh' then: |
| | 1. x[1:4] == 'bcde' |
| | 2. x[ :4] == x[:8 / 2] == 'abcde' |
| | 3. x[2 + 1: ] == x[3:] =='defgh' |
| | 4. x[ : ] == x[:] == 'abcdefgh' |
| | 5. x[4/2:3+1] == x[2:4] == 'cde' |
| | |
| | Note: Both r0 and r1 are assumed to be integers, where |
| | r0 <= r1. They may also be the result of an expression, |
| | in the event they have fractional components truncation |
| | shall be performed. (eg: 1.67 --> 1) |
+----------+---------------------------------------------------------+
| := | Assign the value of x to y. Where y is a mutable string |
| | or string range and x is either a string or a string |
| | range. eg: |
| | 1. y := x |
| | 2. y := 'abc' |
| | 3. y := x[:i + j] |
| | 4. y := '0123456789'[2:7] |
| | 5. y := '0123456789'[2i + 1:7] |
| | 6. y := (x := '0123456789'[2:7]) |
| | 7. y[i:j] := x |
| | 8. y[i:j] := (x + 'abcdefg'[8 / 4:5])[m:n] |
| | |
| | Note: For options 7 and 8 the shorter of the two ranges |
| | will denote the number characters that are to be copied.|
+----------+---------------------------------------------------------+
| + | Concatenation of x and y. Where x and y are strings or |
| | string ranges. eg |
| | 1. x + y |
| | 2. x + 'abc' |
| | 3. x + y[:i + j] |
| | 4. x[i:j] + y[2:3] + '0123456789'[2:7] |
| | 5. 'abc' + x + y |
| | 6. 'abc' + '1234567' |
| | 7. (x + 'a1B2c3D4' + y)[i:2j] |
+----------+---------------------------------------------------------+
| += | Append to x the value of y. Where x is a mutable string |
| | and y is either a string or a string range. eg: |
| | 1. x += y |
| | 2. x += 'abc' |
| | 3. x += y[:i + j] + 'abc' |
| | 4. x += '0123456789'[2:7] |
+----------+---------------------------------------------------------+
| <=> | Swap the values of x and y. Where x and y are mutable |
| | strings. (eg: x <=> y) |
+----------+---------------------------------------------------------+
| [] | The string size operator returns the size of the string |
| | being actioned. |
| | eg: |
| | 1. 'abc'[] == 3 |
| | 2. var max_str_length := max(s0[], s1[], s2[], s3[]) |
| | 3. ('abc' + 'd')[] == 6 |
| | 4. (('abc' + 'xyz')[1:4])[] == 4 |
+----------+---------------------------------------------------------+
(6) Control Structures
+----------+---------------------------------------------------------+
|STRUCTURE | DEFINITION |
+----------+---------------------------------------------------------+
| if | If x is true then return y else return z. |
| | eg: |
| | 1. if (x, y, z) |
| | 2. if ((x + 1) > 2y, z + 1, w / v) |
| | 3. if (x > y) z; |
| | 4. if (x <= 2*y) { z + w }; |
+----------+---------------------------------------------------------+
| if-else | The if-else/else-if statement. Subject to the condition |
| | branch the statement will return either the value of the|
| | consequent or the alternative branch. |
| | eg: |
| | 1. if (x > y) z; else w; |
| | 2. if (x > y) z; else if (w != u) v; |
| | 3. if (x < y) { z; w + 1; } else u; |
| | 4. if ((x != y) and (z > w)) |
| | { |
| | y := sin(x) / u; |
| | z := w + 1; |
| | } |
| | else if (x > (z + 1)) |
| | { |
| | w := abs (x - y) + z; |
| | u := (x + 1) > 2y ? 2u : 3u; |
| | } |
+----------+---------------------------------------------------------+
| switch | The first true case condition that is encountered will |
| | determine the result of the switch. If none of the case |
| | conditions hold true, the default action is assumed as |
| | the final return value. This is sometimes also known as |
| | a multi-way branch mechanism. |
| | eg: |
| | switch |
| | { |
| | case x > (y + z) : 2 * x / abs(y - z); |
| | case x < 3 : sin(x + y); |
| | default : 1 + x; |
| | } |
+----------+---------------------------------------------------------+
| while | The structure will repeatedly evaluate the internal |
| | statement(s) 'while' the condition is true. The final |
| | statement in the final iteration shall be used as the |
| | return value of the loop. |
| | eg: |
| | while ((x -= 1) > 0) |
| | { |
| | y := x + z; |
| | w := u + y; |
| | } |
+----------+---------------------------------------------------------+
| repeat/ | The structure will repeatedly evaluate the internal |
| until | statement(s) 'until' the condition is true. The final |
| | statement in the final iteration shall be used as the |
| | return value of the loop. |
| | eg: |
| | repeat |
| | y := x + z; |
| | w := u + y; |
| | until ((x += 1) > 100) |
+----------+---------------------------------------------------------+
| for | The structure will repeatedly evaluate the internal |
| | statement(s) while the condition is true. On each loop |
| | iteration, an 'incrementing' expression is evaluated. |
| | The conditional is mandatory whereas the initialiser |
| | and incrementing expressions are optional. |
| | eg: |
| | for (var x := 0; (x < n) and (x != y); x += 1) |
| | { |
| | y := y + x / 2 - z; |
| | w := u + y; |
| | } |
+----------+---------------------------------------------------------+
| break | Break terminates the execution of the nearest enclosed |
| break[] | loop, allowing for the execution to continue on external|
| | to the loop. The default break statement will set the |
| | return value of the loop to NaN, where as the return |
| | based form will set the value to that of the break |
| | expression. |
| | eg: |
| | while ((i += 1) < 10) |
| | { |
| | if (i < 5) |
| | j -= i + 2; |
| | else if (i % 2 == 0) |
| | break; |
| | else |
| | break[2i + 3]; |
| | } |
+----------+---------------------------------------------------------+
| continue | Continue results in the remaining portion of the nearest|
| | enclosing loop body to be skipped. |
| | eg: |
| | for (var i := 0; i < 10; i += 1) |
| | { |
| | if (i < 5) |
| | continue; |
| | j -= i + 2; |
| | } |
+----------+---------------------------------------------------------+
| return | Return immediately from within the current expression. |
| | With the option of passing back a variable number of |
| | values (scalar, vector or string). eg: |
| | 1. return [1]; |
| | 2. return [x, 'abx']; |
| | 3. return [x, x + y,'abx']; |
| | 4. return []; |
| | 5. if (x < y) |
| | return [x, x - y, 'result-set1', 123.456]; |
| | else |
| | return [y, x + y, 'result-set2']; |
+----------+---------------------------------------------------------+
| ?: | Ternary conditional statement, similar to that of the |
| | above denoted if-statement. |
| | eg: |
| | 1. x ? y : z |
| | 2. x + 1 > 2y ? z + 1 : (w / v) |
| | 3. min(x,y) > z ? (x < y + 1) ? x : y : (w * v) |
+----------+---------------------------------------------------------+
| ~ | Evaluate each sub-expression, then return as the result |
| | the value of the last sub-expression. This is sometimes |
| | known as multiple sequence point evaluation. |
| | eg: |
| | ~(i := x + 1, j := y / z, k := sin(w/u)) == (sin(w/u))) |
| | ~{i := x + 1; j := y / z; k := sin(w/u)} == (sin(w/u))) |
+----------+---------------------------------------------------------+
| [*] | Evaluate any consequent for which its case statement is |
| | true. The return value will be either zero or the result|
| | of the last consequent to have been evaluated. |
| | eg: |
| | [*] |
| | { |
| | case (x + 1) > (y - 2) : x := z / 2 + sin(y / pi); |
| | case (x + 2) < abs(y + 3) : w / 4 + min(5y,9); |
| | case (x + 3) == (y * 4) : y := abs(z / 6) + 7y; |
| | } |
+----------+---------------------------------------------------------+
| [] | The vector size operator returns the size of the vector |
| | being actioned. |
| | eg: |
| | 1. v[] |
| | 2. max_size := max(v0[],v1[],v2[],v3[]) |
+----------+---------------------------------------------------------+
Note01: In the tables above, the symbols x, y, z, w, u and v where
appropriate may represent any of one the following:
1. Literal numeric/string value
2. A variable
3. A vector element
4. A vector
5. A string
6. An expression comprised of [1], [2] or [3] (eg: 2 + x / vec[3])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 09 - FUNDAMENTAL TYPES]
ExprTk supports three fundamental types which can be used freely in
expressions. The types are as follows:
(1) Scalar
(2) Vector
(3) String
(1) Scalar Type
The scalar type is a singular numeric value. The underlying type is
that used to specialise the ExprTk components (float, double, long
double, MPFR et al).
(2) Vector Type
The vector type is a fixed size sequence of contiguous scalar values.
A vector can be indexed resulting in a scalar value. Operations
between a vector and scalar will result in a vector with a size equal
to that of the original vector, whereas operations between vectors
will result in a vector of size equal to that of the smaller of the
two. In both mentioned cases, the operations will occur element-wise.
(3) String Type
The string type is a variable length sequence of 8-bit chars. Strings
can be assigned and concatenated to one another, they can also be
manipulated via sub-ranges using the range definition syntax. Strings
however can not interact with scalar or vector types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[SECTION 10 - COMPONENTS]
There are three primary components, that are specialised upon a given
numeric type, which make up the core of ExprTk. The components are as
follows:
(1) Symbol Table exprtk::symbol_table<NumericType>
(2) Expression exprtk::expression<NumericType>
(3) Parser exprtk::parser<NumericType>
(1) Symbol Table
A structure that is used to store references to variables, constants
and functions that are to be used within expressions. Furthermore in
the context of composited recursive functions the symbol table can
also be thought of as a simple representation of a stack specific for
the expression(s) that reference it. The following is a list of the
types a symbol table can handle:
(a) Numeric variables
(b) Numeric constants
(c) Numeric vector elements
(d) String variables
(e) String constants
(f) Functions
(g) Vararg functions
During the compilation process if an expression is found to require
any of the elements noted above, the expression's associated
symbol_table will be queried for the element and if present a
reference to the element will be embedded within the expression's AST.
This allows for the original element to be modified independently of
the expression instance and to also allow the expression to be
evaluated using the current value of the element.
The example below demonstrates the relationship between variables,
symbol_table and expression. Note the variables are modified as they
normally would in a program, and when the expression is evaluated the
current values assigned to the variables shall be used.
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
double x = 0;
double y = 0;
symbol_table_t symbol_table;
expression_t expression;
parser_t parser;
std::string expression_string = "x * y + 3";
symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);
expression.register_symbol_table(symbol_table);
parser.compile(expression_string,expression);
x = 1.0;
y = 2.0;
expression.value(); // 1 * 2 + 3
x = 3.7;
expression.value(); // 3.7 * 2 + 3
y = -9.0;
expression.value(); // 3.7 * -9 + 3
// 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001
for (x = 0.0; x < 100.0; x += 0.0001)
{
expression.value(); // x * -9 + 3
}
Note02: Any variable reference provided to a given symbol_table
instance, must have a lifetime at least as long as the lifetime of the
symbol_table instance. In the event the variable reference is
invalidated before the symbol_table or any dependent expression
instances have been destructed, then any associated expression
evaluations or variable referencing via the symbol_table instance will
result in undefined behaviour.
The following bit of code instantiates a symbol_table and expression
instance, then proceeds to demonstrate various ways in which
references to variables can be added to the symbol_table, and how
those references are subsequently invalidated resulting in various
forms of undefined behaviour.
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
symbol_table_t symbol_table;
expression_t expression;
std::deque<double > y {1.1, 2.2, 3.3};
std::vector<double> z {4.4, 5.5, 6.6};
double* w = new double(123.456);
{
double x = 123.4567;
symbol_table.add_variable("x", x);
} // Reference to variable x has been invalidated
symbol_table.add_variable("y", y.back());
y.pop_back(); // Reference to variable y has been invalidated
symbol_table.add_variable("z", z.front());
z.erase(z.begin());
// Reference to variable z has been invalidated
symbol_table.add_variable("w", *w);
delete w; // Reference to variable w has been invalidated
const std::string expression_string = "x + y / z * w";
// Compilation of expression will succeed
parser.compile(expression_string,expression);
expression.value();
// Evaluation will result in undefined behaviour
// due to 'x' and 'w' having been destroyed.
symbol_table.get_variable("x")->ref() = 135.791;
// Assignment will result in undefined behaviour
A compiled expression that references variables from a symbol_table is
dependent on that symbol_table instance and the variables it holds
being valid.
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
symbol_table_t symbol_table;
expression_t expression;
double x = 123.456;
symbol_table.add_variable("x", x);
const std::string expression_string = "(x + 1) / 2";
// Compilation of the expression will succeed
parser.compile(expression_string,expression);
// Clear all variables from symbol_table
symbol_table.clear();
expression.value();
// Evaluation will result in undefined behaviour
// because the reference to 'x' having been destroyed
// during the clearing of the symbol_table
In the above example, an expression is compiled that references
variable "x". As part of the compilation process the node holding the
variable "x" is obtained from the symbol_table and embedded in the AST
of the expression - in short the expression is now referencing the
node that holds the variable "x". The following diagram depicts the
dependencies between the variable x, the symbol table and the
expression:
+--[Symbol Table]--+
| |
| +- ------+ |
| | x-node | |
| +-----A--+ | +--[Expression]--+
+---|---|----------+ | +---------+ |
v | | | A.S.T | |
| +--------<--------[.] | |
+-----+ | +---------+ |
| +----------------+
+-v-[variable]---+
| x: 123.456 |
+----------------+
When the clear method is called on the symbol table the X-Node is
destroyed, so now the expression is referencing a node that has been
destroyed. From this point onwards any attempts to reference the
expression instance will result in undefined behaviour. Simply put the
above example violates the requirement that the lifetime of any
objects referenced by expressions should exceed the lifetime of the
expression instance.
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
symbol_table_t symbol_table;
expression_t expression;
double x = 123.456;
symbol_table.add_variable("x", x);
const std::string expression_string = "(x + 1) / 2";
// Compilation of the expression will succeed
parser.compile(expression_string,expression);
expression.value();
// Release the expression and its dependents
expression.release();
// Clear all variables from symbol_table
symbol_table.clear();
expression.value();
// Will return null_node value of NaN
In the above example the expression is released before the associated
symbol_table is cleared of its variables, which resolves the undefined
behaviour issue noted in the previous example.
Note03: It is possible to register multiple symbol_tables with a
single expression object. In the event an expression has multiple
symbol tables, and where there exists conflicts between symbols, the
compilation stage will resolve the conflicts based on the order of
registration of the symbol_tables to the expression. For a more
expansive discussion please review section [17 - Hierarchies Of Symbol
Tables]
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
symbol_table_t symbol_table0;
symbol_table_t symbol_table1;
expression_t expression;
parser_t parser;
double x0 = 123.0;
double x1 = 678.0;
std::string expression_string = "x + 1";
symbol_table0.add_variable("x",x0);
symbol_table1.add_variable("x",x1);
expression.register_symbol_table(symbol_table0);
expression.register_symbol_table(symbol_table1);
parser.compile(expression_string,expression);
expression.value(); // 123 + 1
The symbol table supports adding references to external instances of
types that can be accessed within expressions via the following
methods:
1. bool add_variable (const std::string& name, scalar_t& )
2. bool add_constant (const std::string& name, const scalar_t& )
3. bool add_stringvar (const std::string& name, std::string& )
4. bool add_vector (const std::string& name, vector_type& )
5. bool add_function (const std::string& name, function_t& )
6. bool create_stringvar(const std::string& name,const std::string&)
7. bool create_variable (const std::string& name, const T& )
Note04: The 'vector' type must be comprised from a contiguous array of
scalars with a size that is larger than zero. The vector type itself
can be any one of the following:
1. std::vector<scalar_t>
2. scalar_t(&v)[N]
3. scalar_t* and array size
4. exprtk::vector_view<scalar_t>
When registering a variable, vector, string or function with an
instance of a symbol_table, the call to 'add_...' may fail and return
a false result due to one or more of the following reasons:
1. Variable name contains invalid characters or is ill-formed
2. Variable name conflicts with a reserved word (eg: 'while')
3. Variable name conflicts with a previously registered variable
4. A vector of size (length) zero is being registered
5. A free function exceeding fifteen parameters is being registered
6. The symbol_table instance is in an invalid state
Note05: The symbol_table has a method called clear, which when invoked
will clear all variables, vectors, strings and functions registered
with the symbol_table instance. If this method is to be called, then
one must make sure that all compiled expression instances that
reference variables belonging to that symbol_table instance are
released (aka call release method on expression) before calling the
clear method on the symbol_table instance, otherwise undefined
behaviours will occur.
A further property of symbol tables is that they can be classified at
instantiation as either being mutable (by default) or immutable. This
property determines if variables, vectors or strings registered with
the symbol table can undergo modifications within expressions that
reference them. The following demonstrates construction of an
immutable symbol table instance:
symbol_table_t immutable_symbol_table
(symbol_table_t::symtab_mutability_type::e_immutable);