Repository navigation
Expand file tree
/
Copy pathMathParser.bas
More file actions
11959 lines (11144 loc) · 417 KB
/
Copy pathMathParser.bas
File metadata and controls
11959 lines (11144 loc) · 417 KB
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
#include once "crt.bi"
#include once "Inc\MathParser.bi"
#include once "MathParserRawResult.bas"
extern "C"
declare function acosh (byval x as double) as double
declare function asinh (byval x as double) as double
declare function atanh (byval x as double) as double
'' CRT libm (not FB intrinsics: built-in sin/cos/tan mishandle |x| >= 2^63).
declare function libc_sin alias "sin" (byval x as double) as double
declare function libc_cos alias "cos" (byval x as double) as double
declare function libc_tan alias "tan" (byval x as double) as double
end extern
private function LibSin(byval x as Double) as Double
return libc_sin(x)
end function
private function LibCos(byval x as Double) as Double
return libc_cos(x)
end function
private function LibTan(byval x as Double) as Double
return libc_tan(x)
end function
const FB_STR_AT as string = " at "
const FB_STR_LINE_1_PREFIX as string = "line 1, "
const FB_STR_COL as string = "col "
const FB_STR_COLON as string = ": "
const FB_STR_COMMA as string = ", "
const FB_STR_RAND as string = "rand"
const FB_STR_RANDOM as string = "random"
const FB_STR_BIN as string = "bin"
const FB_STR_HEX as string = "hex"
const FB_STR_OCT as string = "oct"
const FB_STR_POW as string = "pow"
const FB_STR_ATAN2 as string = "atan2"
const FB_STR_SIN as string = "sin"
const FB_STR_COS as string = "cos"
const FB_STR_TAN as string = "tan"
const FB_STR_ASIN as string = "asin"
const FB_STR_ARCSIN as string = "arcsin"
const FB_STR_ACOS as string = "acos"
const FB_STR_ARCCOS as string = "arccos"
const FB_STR_ATAN as string = "atan"
const FB_STR_ARCTAN as string = "arctan"
const FB_STR_SINH as string = "sinh"
const FB_STR_COSH as string = "cosh"
const FB_STR_TANH as string = "tanh"
const FB_STR_ACOSH as string = "acosh"
const FB_STR_ASINH as string = "asinh"
const FB_STR_ATANH as string = "atanh"
const FB_STR_EXP as string = "exp"
const FB_STR_LOG as string = "log"
const FB_STR_LN as string = "ln"
const FB_STR_LOG10 as string = "log10"
const FB_STR_SQRT as string = "sqrt"
const FB_STR_SQR as string = "sqr"
const FB_STR_INT as string = "int"
const FB_STR_FRAC as string = "frac"
const FB_STR_FRACT as string = "fract"
const FB_STR_ABS as string = "abs"
const FB_STR_FLOOR as string = "floor"
const FB_STR_CEIL as string = "ceil"
const FB_STR_TRUNC as string = "trunc"
const FB_STR_ROUND as string = "round"
const FB_STR_SIGN as string = "sign"
const FB_STR_DEG as string = "deg"
const FB_STR_RAD as string = "rad"
const FB_STR_SUM as string = "sum"
const FB_STR_MEDIAN as string = "median"
const FB_STR_VARIANCE as string = "variance"
const FB_STR_STDDEV as string = "stddev"
const FB_STR_SORT as string = "sort"
const FB_STR_SORTED as string = "sorted"
const FB_STR_SORTBY as string = "sortby"
const FB_STR_RATIO as string = "ratio"
const FB_STR_RANGE as string = "range"
const FB_STR_REVERSE as string = "reverse"
const FB_STR_REVERSED as string = "reversed"
const FB_STR_UNIQUE as string = "unique"
const FB_STR_UNPACK as string = "unpack"
const FB_STR_FLAT as string = "flat"
const FB_STR_REPEAT as string = "repeat"
const FB_STR_LEN as string = "len"
const FB_STR_LENGTH as string = "length"
const FB_STR_FACT as string = "fact"
const FB_STR_FACTORIAL as string = "factorial"
const FB_STR_FACTORINT as string = "factorint"
const FB_STR_DOUBLE_ASTERISK as string = "**"
const FB_STR_AVG as string = "avg"
const FB_STR_MEAN as string = "mean"
const FB_STR_MOD as string = "mod"
const FB_STR_CLAMP as string = "clamp"
const FB_STR_HYPOT as string = "hypot"
const FB_STR_GCD as string = "gcd"
const FB_STR_LCM as string = "lcm"
const FB_STR_NCR as string = "ncr"
const FB_STR_NPR as string = "npr"
const FB_STR_PRODUCT as string = "product"
const FB_STR_PROD as string = "prod"
const FB_STR_MIN as string = "min"
const FB_STR_MAX as string = "max"
const FB_STR_UHEX as string = "uhex"
const FB_STR_UOCT as string = "uoct"
const FB_STR_UBIN as string = "ubin"
const FB_STR_NOT as string = "not"
const FB_STR_AND as string = "and"
const FB_STR_OR as string = "or"
const FB_STR_PI as string = "pi"
const FB_STR_E as string = "e"
const FB_STR_I as string = "i"
const FB_STR_INF as string = "inf"
const FB_STR_NAN as string = "nan"
const FB_STR_PAR as string = "()"
const FB_STR_PAR_MIN_COMMA_MAX as string = "(min, max)"
const FB_STR_PAR_DOTDOTDOT as string = "(...)"
const FB_STR_PAR_VALUE_COMMA_POWER as string = "(value, power)"
const FB_STR_PAR_Y_COMMA_X as string = "(y, x)"
const FB_STR_PAR_ANGLE as string = "(angle)"
const FB_STR_PAR_VALUE as string = "(value)"
const FB_STR_PAR_VALUE_COMMA_BASE as string = "(value, base)"
const FB_STR_PAR_N as string = "(n)"
const FB_STR_PAR_VALUE_COMMA_DIVISOR as string = "(value, divisor)"
const FB_STR_PAR_VALUE_COMMA_MIN_COMMA_MAX as string = "(value, min, max)"
const FB_STR_PAR_X_COMMA_Y as string = "(x, y)"
const FB_STR_PAR_A_COMMA_B as string = "(a, b)"
const FB_STR_PAR_N_COMMA_R as string = "(n, r)"
const FB_STR_PAR_X_COMMA_N as string = "(x, n)"
const FB_STR_PAR_X as string = "(x)"
const FB_STR_PAR_START_COMMA_STOP_COMMA_STEP as string = "(start, stop [, step])"
const FB_STR_PAR_STEP_MUST_NOT_BE_ZERO as string = "() step must not be zero"
const FB_STR_PAR_PRODUCES_NO_VALUES as string = "() produces no values"
const FB_STR_PAR_PRODUCES_TOO_MANY_VALUES as string = "() produces too many values"
const BUILTIN_MAX_PRODUCED_ITEMS as Integer = 1000
const FB_STR_PAR_ANS as string = "(ans)"
const FB_STR_PREFIX_HEX as string = "0x"
const FB_STR_PREFIX_OCT as string = "0o"
const FB_STR_PREFIX_BIN as string = "0b"
const FB_STR_ANS as string = "ans"
const FB_STR_FORMAL_VALIDATION_PROBE as string = "_"
const FB_STR_INDEXING_REQUIRES_AN_ARRAY_VALUE as string = "indexing requires an array value"
const FB_STR_MISSING_INDEX as string = "missing index"
const FB_STR_ARRAY_INDEX_MUST_BE_A_SCALAR as string = "array index must be a scalar integer"
const FB_STR_ARRAY_INDEX_MUST_BE_AN_INTEGER as string = "array index must be an integer"
const FB_STR_MISMATCHED_CLOSING_PARENTHESIS as string = "mismatched closing parenthesis"
const FB_STR_MISMATCHED_CLOSING_BRACE as string = "mismatched closing brace"
const FB_STR_MISSING_CLOSING_BRACKET as string = "missing closing bracket"
const FB_STR_ARRAY_INDEX_IS_OUT_OF_RANGE as string = "array index is out of range"
const FB_STR_SLICE_STEP_MUST_NOT_BE_ZERO as string = "slice step must not be zero"
const FB_STR_PAR_EXPECTS as string = "() expects "
const FB_STR_ARGUMENT_PAR_S_COMMA as string = " argument(s), "
const FB_STR_GIVEN as string = " given"
const FB_STR_RECURSIVE_USER_FUNCTION_CALL_COLON as string = "recursive function call: "
const FB_STR_USER_FUNCTION_CALL_STACK_OVERFLOW as string = "function call stack overflow"
const FB_STR_MODULO_OPERANDS_MUST_BE_INTEGER_VALUES as string = "modulo operands must be integer values"
const FB_STR_BITWISE_OPERANDS_MUST_BE_INTEGER_VALUES as string = "bitwise operands must be integer values"
const FB_STR_INCOMPATIBLE_OPERANDS as string = "incompatible operands"
const FB_STR_TIME_EMPTY_SEGMENT as string = "time literal: empty segment between colons"
const FB_STR_TIME_INVALID_SEGMENT as string = "time literal: invalid segment"
const FB_STR_TIME_COMPACT_EXPECTED_UNIT as string = "compact time literal: expected unit suffix"
const FB_STR_TIME_COMPACT_UNIT_ORDER as string = "compact time literal: unit order or duplicate unit"
const FB_STR_TIME_COMPACT_INVALID_SUFFIX as string = "compact time literal: invalid suffix"
const FB_STR_TIME_NEGATIVE_SEGMENT as string = "time literal: negative segment"
const FB_STR_TIME_NON_FINITE as string = "time value: non-finite operand"
const FB_STR_TIME_ARRAY_MIXED as string = "time values cannot be mixed with non-time values"
const FB_STR_TIME_EXPECTS_TIME_ARG as string = "() expects a time value"
const FB_STR_MILLISECOND as string = "millisecond"
const FB_STR_SECOND as string = "second"
const FB_STR_MINUTE as string = "minute"
const FB_STR_HOUR as string = "hour"
const FB_STR_DAY as string = "day"
const FB_STR_MILLISECONDS as string = "milliseconds"
const FB_STR_SECONDS as string = "seconds"
const FB_STR_MINUTES as string = "minutes"
const FB_STR_HOURS as string = "hours"
const FB_STR_DAYS as string = "days"
const FB_STR_REAL as string = "real"
const FB_STR_IMAG as string = "imag"
const FB_STR_PHASE as string = "phase"
const FB_STR_POLAR as string = "polar"
const FB_STR_CART as string = "cart"
const FB_STR_CONJ as string = "conj"
const FB_STR_PAR_EXPECTS_AT_LEAST as string = "() expects at least "
const FB_STR_ARGUMENT as string = " argument"
const FB_STR_ARGUMENTS as string = " arguments"
const FB_STR_MISSING_OPENING_BRACKET as string = "missing opening bracket"
const FB_STR_UNEXPECTED_COMMA as string = "unexpected comma"
const FB_STR_MISMATCHED_CLOSING_BRACKET as string = "mismatched closing bracket"
const FB_STR_MISSING_CLOSING_PARENTHESIS as string = "missing closing parenthesis"
const FB_STR_NUMERIC_ERROR_IN as string = "numeric error in "
const FB_STR_PAR_EXPECTS_A_NON_DASH as string = "() expects a non-negative integer"
const FB_STR_PAR_EXPECTS_A_POSITIVE_INTEGER as string = "() expects a positive integer"
const FB_STR_PAR_EXPECTS_SCALAR_VALUES as string = "() expects scalar values"
const FB_STR_PAR_EXPECTS_SCALAR_MIN_SLASH as string = "() expects scalar min/max"
const FB_STR_PAR_EXPECTS_INTEGER_VALUES as string = "() expects integer values"
const FB_STR_INVALID_HEX_LITERAL as string = "invalid hex literal"
const FB_STR_INVALID_BINARY_LITERAL as string = "invalid binary literal"
const FB_STR_INVALID_OCTAL_LITERAL as string = "invalid octal literal"
const FB_STR_UNEXPECTED_TOKEN as string = "unexpected token"
const FB_STR_HINT_PREFIX as string = "function: "
const FB_STR_ARRAY_ELEMENT_MUST_BE_SCALAR as string = "array element must be scalar"
const FB_STR_EXPRESSION_IS_TOO_LONG as string = "expression is too long"
const FB_STR_EMPTY_STATEMENT as string = "empty statement"
const FB_STR_RESERVED_FUNCTION_NAME_COLON as string = "reserved function name: "
const FB_STR_RESERVED_CONSTANT_NAME_COLON as string = "reserved constant name: "
const FB_STR_RESERVED_BUILTIN_VARIABLE_NAME_COLON as string = "reserved built-in variable name: "
const FB_STR_DUPLICATE_PARAMETER_NAME_COLON as string = "duplicate parameter name: "
const FB_STR_FUNCTION_BODY_IS_EMPTY as string = "function body is empty"
const FB_STR_FAILED_TO_PARSE_USER_FUNCTION_BODY as string = "failed to parse user function body"
const FB_STR_UNEXPECTED_INPUT as string = "unexpected characters"
const FB_STR_INTERNAL_UNARY_OP as string = "internal unary op"
const FB_STR_INTERNAL_BINARY_OP as string = "internal binary op"
const FB_STR_INTERNAL_EVAL_ERROR as string = "internal eval error"
const FB_STR_NUMERIC_ERROR_IN_POWER_OPERATION as string = "numeric error in power operation"
const FB_STR_NUMERIC_ERROR_IN_EXPRESSION as string = "numeric error in expression"
const FB_STR_MAX_EVALUATION_DEPTH_REACHED as string = "max evaluation depth reached"
const FB_STR_INVALID_NUMERIC_LITERAL as string = "invalid numeric literal"
const FB_STR_PERCENTAGE_REQUIRES_SCALAR_VALUE as string = "percentage requires scalar value"
const FB_STR_FAILED_TO_BUILD_ARRAY_LITERAL as string = "failed to build array literal"
const FB_STR_INTERNAL_ERROR_IN_AGGREGATE_BUILTIN as string = "internal error in aggregate builtin"
const FB_STR_INTERNAL_ERROR_IN_SCALAR_BINARY_BUILTIN as string = "internal error in scalar binary builtin"
const FB_STR_INTERNAL_ERROR_IN_UNARY_MATH_BUILTIN as string = "internal error in unary math builtin"
const FB_STR_UNEXPECTED_TOKEN_AFTER_EXPRESSION as string = "unexpected token after expression"
const FB_STR_SCALAR_ONLY_EXPRESSION_ENCOUNTERED_NON as string = "scalar-only expression encountered non-scalar value"
const FB_STR_PARSE_FAILED as string = "parse failed"
const FB_STR_DEFINED as string = "defined "
const FB_STR_UNKNOWN_VARIABLE_COLON as string = "unknown variable: "
const FB_STR_USER_DEFINED_FUNCTION_COLON as string = "user-defined function: "
const FB_STR_UNKNOWN_FUNCTION_COLON as string = "unknown function: "
const FB_STR_SORTBY_EXPECTS_ONE_FUNCTION as string = "sortby expects exactly one function"
const FB_STR_SORTBY_EXPECTS_UNARY_FUNCTION as string = "sortby expects a function that takes 1 parameter"
const RATIO_APPROX_EPS as Double = 1e-14
const RATIO_MAX_DENOMINATOR as LongInt = 10000000
const RATIO_MAX_POWER10_EXP as Integer = 18
const RATIO_SEMICONV_LINEAR_THRESH as Integer = 64
const FB_STR_SORTBY_KEY_MUST_BE_SCALAR_OR_ARRAY as string = "sortby key function must return a scalar or an array"
const LAMBDA_BODY_UNTIL_RPAREN as Integer = 1
const LAMBDA_BODY_UNTIL_SEMICOLON_EOF as Integer = 2
const LAMBDA_BODY_UNTIL_SORTBY_DELIM as Integer = 3
const FB_STR_PAR_ARRAY_COMMA_FUNC as string = "(array, func)"
const FB_STR_SEMICOLON_UNKNOWN_FUNCTION_COLON as string = "; unknown function: "
const FB_U64_MAX as ULongInt = &hFFFFFFFFFFFFFFFFULL
const FB_I64_MIN as LongInt = -9223372036854775807 - 1 ' -0x8000000000000000
const FB_I64_MAX as LongInt = 9223372036854775807 ' 0x7FFFFFFFFFFFFFFF
const FB_I64_MAX_U as ULongInt = 9223372036854775807
const FB_I64_MIN_MAG_U as ULongInt = &h8000000000000000ULL
const FB_I64_MIN_D as Double = -9223372036854775808.0
const FB_I64_MAX_D as Double = 9223372036854775807.0
const FB_MAX_EXACT_INT_FROM_DOUBLE as Double = 9007199254740992.0 ' 2^53
'' IEEE double: 2^64 (next representable above UINT64_MAX).
const FB_2_POW_64_D as Double = 1.8446744073709551616e+19
const FB_PI_VAL as Double = 4.0 * atn(1.0) ' pi
' -----------------------------------------------------------------------------
' ASCII byte constants (single-byte stream; multi-byte UTF-8 not interpreted)
' -----------------------------------------------------------------------------
const CHAR_NUL as UByte = 0 ' string terminator / NUL
const CHAR_TAB as UByte = 9 ' horizontal tab
const CHAR_LF as UByte = 10 ' line feed
const CHAR_CR as UByte = 13 ' carriage return
const CHAR_SPACE as UByte = 32 ' space
const CHAR_EXCLAMATION as UByte = 33 ' !
const CHAR_HASH as UByte = 35 ' #
const CHAR_PERCENT as UByte = 37 ' %
const CHAR_AMPERSAND as UByte = 38 ' &
const CHAR_LPAREN as UByte = 40 ' (
const CHAR_RPAREN as UByte = 41 ' )
const CHAR_ASTERISK as UByte = 42 ' *
const CHAR_PLUS as UByte = 43 ' +
const CHAR_COMMA as UByte = 44 ' ,
const CHAR_MINUS as UByte = 45 ' -
const CHAR_DOT as UByte = 46 ' .
const CHAR_DIVIDE as UByte = 47 ' /
const CHAR_DIGIT_0 as UByte = 48 ' digit 0
const CHAR_DIGIT_1 as UByte = 49 ' digit 1
const CHAR_DIGIT_2 as UByte = 50 ' digit 2
const CHAR_DIGIT_3 as UByte = 51 ' digit 3
const CHAR_DIGIT_4 as UByte = 52 ' digit 4
const CHAR_DIGIT_5 as UByte = 53 ' digit 5
const CHAR_DIGIT_6 as UByte = 54 ' digit 6
const CHAR_DIGIT_7 as UByte = 55 ' digit 7
const CHAR_DIGIT_8 as UByte = 56 ' digit 8
const CHAR_DIGIT_9 as UByte = 57 ' digit 9
const CHAR_COLON as UByte = 58 ' :
const CHAR_SEMICOLON as UByte = 59 ' ;
const CHAR_LESS_THAN as UByte = 60 ' <
const CHAR_EQUALS as UByte = 61 ' =
const CHAR_GREATER_THAN as UByte = 62 ' >
const CHAR_QUESTION as UByte = 63 ' ?
const CHAR_AT as UByte = 64 ' @
const CHAR_A as UByte = 65 ' A
const CHAR_B as UByte = 66 ' B
const CHAR_C as UByte = 67 ' C
const CHAR_D as UByte = 68 ' D
const CHAR_E as UByte = 69 ' E
const CHAR_F as UByte = 70 ' F
const CHAR_G as UByte = 71 ' G
const CHAR_H as UByte = 72 ' H
const CHAR_I as UByte = 73 ' I
const CHAR_J as UByte = 74 ' J
const CHAR_K as UByte = 75 ' K
const CHAR_L as UByte = 76 ' L
const CHAR_M as UByte = 77 ' M
const CHAR_N as UByte = 78 ' N
const CHAR_O as UByte = 79 ' O
const CHAR_P as UByte = 80 ' P
const CHAR_Q as UByte = 81 ' Q
const CHAR_R as UByte = 82 ' R
const CHAR_S as UByte = 83 ' S
const CHAR_T as UByte = 84 ' T
const CHAR_U as UByte = 85 ' U
const CHAR_V as UByte = 86 ' V
const CHAR_W as UByte = 87 ' W
const CHAR_X as UByte = 88 ' X
const CHAR_Y as UByte = 89 ' Y
const CHAR_Z as UByte = 90 ' Z
const CHAR_LBRACKET as UByte = 91 ' [
const CHAR_BACKSLASH as UByte = 92 ' backslash
const CHAR_RBRACKET as UByte = 93 ' ]
const CHAR_CARET as UByte = 94 ' ^
const CHAR_UNDERSCORE as UByte = 95 ' _
const CHAR_LC_A as UByte = 97 ' a
const CHAR_LC_B as UByte = 98 ' b
const CHAR_LC_C as UByte = 99 ' c
const CHAR_LC_D as UByte = 100 ' d
const CHAR_LC_E as UByte = 101 ' e
const CHAR_LC_F as UByte = 102 ' f
const CHAR_LC_G as UByte = 103 ' g
const CHAR_LC_H as UByte = 104 ' h
const CHAR_LC_I as UByte = 105 ' i
const CHAR_LC_J as UByte = 106 ' j
const CHAR_LC_K as UByte = 107 ' k
const CHAR_LC_L as UByte = 108 ' l
const CHAR_LC_M as UByte = 109 ' m
const CHAR_LC_N as UByte = 110 ' n
const CHAR_LC_O as UByte = 111 ' o
const CHAR_LC_P as UByte = 112 ' p
const CHAR_LC_Q as UByte = 113 ' q
const CHAR_LC_R as UByte = 114 ' r
const CHAR_LC_S as UByte = 115 ' s
const CHAR_LC_T as UByte = 116 ' t
const CHAR_LC_U as UByte = 117 ' u
const CHAR_LC_V as UByte = 118 ' v
const CHAR_LC_W as UByte = 119 ' w
const CHAR_LC_X as UByte = 120 ' x
const CHAR_LC_Y as UByte = 121 ' y
const CHAR_LC_Z as UByte = 122 ' z
const CHAR_LBRACE as UByte = 123 ' {
const CHAR_PIPE as UByte = 124 ' |
const CHAR_RBRACE as UByte = 125 ' }
const CHAR_TILDE as UByte = 126 ' ~
enum ValueKind
VK_SCALAR = 0
VK_ARRAY = 1
VK_FUNCTION_REF = 2
VK_INLINE_LAMBDA = 3
end enum
enum ScalarStorageKind
SSK_FLOATINGPOINT = 0
SSK_INT64 = 1
SSK_UINT64 = 2
SSK_TIME = 3
end enum
enum ScalarFlags
SVF_EXACT_INT64_VALID = &h01
SVF_EXACT_UINT64_VALID = &h02
SVF_DEC_SCI_POW63_HIGH = &h10
SVF_IMAG_EXACT_INT64_VALID = &h20
SVF_IMAG_EXACT_UINT64_VALID = &h40
SVF_RENDER_RATIONAL = &h80
SVF_IMAG_RENDER_RATIONAL = &h100
SVF_RENDER_INT_POWER = &h200
end enum
enum EvalFlags
EVF_EXPAND_ARGS = &h01
EVF_RENDER_UNSIGNED = &h02
EVF_RENDER_RATIONAL = &h04
EVF_RENDER_BASE_SHIFT = 8
EVF_RENDER_BASE_MASK = &h0000FF00
end enum
enum BuiltinFunctionId
FUNC_RAND = 0
FUNC_RANDOM
FUNC_BIN
FUNC_HEX
FUNC_OCT
FUNC_POW
FUNC_ATAN2
FUNC_SIN
FUNC_COS
FUNC_TAN
FUNC_ASIN
FUNC_ACOS
FUNC_ATAN
FUNC_SINH
FUNC_COSH
FUNC_TANH
FUNC_ACOSH
FUNC_ASINH
FUNC_ATANH
FUNC_EXP
FUNC_LOG
FUNC_LN
FUNC_LOG10
FUNC_SQRT
FUNC_SQR
FUNC_INT
FUNC_FRAC
FUNC_ABS
FUNC_FLOOR
FUNC_CEIL
FUNC_TRUNC
FUNC_ROUND
FUNC_SIGN
FUNC_DEG
FUNC_RAD
FUNC_SUM
FUNC_MEDIAN
FUNC_VARIANCE
FUNC_STDDEV
FUNC_SORT
FUNC_SORTBY
FUNC_RATIO
FUNC_RANGE
FUNC_REVERSE
FUNC_UNIQUE
FUNC_UNPACK
FUNC_FLAT
FUNC_REPEAT
FUNC_LEN
FUNC_FACT
FUNC_FACTORINT
FUNC_AVG
FUNC_MEAN
FUNC_MOD
FUNC_CLAMP
FUNC_HYPOT
FUNC_GCD
FUNC_LCM
FUNC_NCR
FUNC_NPR
FUNC_PRODUCT
FUNC_MIN
FUNC_MAX
FUNC_UHEX
FUNC_UOCT
FUNC_UBIN
FUNC_MILLISECONDS
FUNC_SECONDS
FUNC_MINUTES
FUNC_HOURS
FUNC_DAYS
FUNC_REAL
FUNC_IMAG
FUNC_PHASE
FUNC_POLAR
FUNC_CART
FUNC_CONJ
FUNC__COUNT
end enum
enum ScalarExactKind
SEK_SIGNED = 0
SEK_UNSIGNED
end enum
enum UnaryScalarKind
USK_NONE = 0
USK_PRIMARY_TRIG
USK_INVERSE_TRIG
USK_HYPERBOLIC_TRIG
USK_INVERSE_HYPERBOLIC_TRIG
USK_EXP
USK_LN
USK_LOG10
USK_SQRT
USK_SQR
USK_ROUNDING
USK_FRAC
USK_ABS
USK_SIGN
USK_DEG
USK_RAD
end enum
'' Static parse/eval error ids (order matches C++ ParseErrorId / kParseErrorTexts).
enum ParseErrorId
PARSE_ERR_UNEXPECTED_COMMA = 0
PARSE_ERR_INDEXING_REQUIRES_ARRAY
PARSE_ERR_MISSING_INDEX
PARSE_ERR_ARRAY_INDEX_MUST_BE_SCALAR
PARSE_ERR_ARRAY_INDEX_MUST_BE_INTEGER
PARSE_ERR_ARRAY_INDEX_OUT_OF_RANGE
PARSE_ERR_MISSING_CLOSING_BRACKET
PARSE_ERR_MISSING_CLOSING_PARENTHESIS
PARSE_ERR_MISMATCHED_CLOSING_PARENTHESIS
PARSE_ERR_MISMATCHED_CLOSING_BRACKET
PARSE_ERR_MISMATCHED_CLOSING_BRACE
PARSE_ERR_BITWISE_INTEGER_OPERANDS
PARSE_ERR_MODULO_INTEGER_OPERANDS
PARSE_ERR_INCOMPATIBLE_OPERANDS
PARSE_ERR_INVALID_HEX_LITERAL
PARSE_ERR_INVALID_BINARY_LITERAL
PARSE_ERR_INVALID_OCTAL_LITERAL
PARSE_ERR_INTERNAL_UNARY_OP
PARSE_ERR_INTERNAL_BINARY_OP
PARSE_ERR_INTERNAL_EVAL_ERROR
PARSE_ERR_NUMERIC_ERROR_IN_POWER_OPERATION
PARSE_ERR_NUMERIC_ERROR_IN_EXPRESSION
PARSE_ERR_USER_FUNCTION_CALL_STACK_OVERFLOW
PARSE_ERR_MAX_EVALUATION_DEPTH_REACHED
PARSE_ERR_INVALID_NUMERIC_LITERAL
PARSE_ERR_PERCENTAGE_REQUIRES_SCALAR_VALUE
PARSE_ERR_FAILED_TO_BUILD_ARRAY_LITERAL
PARSE_ERR_INTERNAL_AGGREGATE_BUILTIN
PARSE_ERR_INTERNAL_SCALAR_BINARY_BUILTIN
PARSE_ERR_INTERNAL_UNARY_MATH_BUILTIN
PARSE_ERR_UNEXPECTED_TOKEN_AFTER_EXPRESSION
PARSE_ERR_SCALAR_ONLY_EXPRESSION_ENCOUNTERED_NON
PARSE_ERR_PARSE_FAILED
PARSE_ERR_UNEXPECTED_TOKEN
PARSE_ERR_UNEXPECTED_INPUT
PARSE_ERR_COUNT
end enum
enum AggregateFoldMode
AFM_REAL = 0
AFM_COMPLEX
AFM_TIME
end enum
enum BuiltinCategory
BC_RAND = 0
BC_SCALAR_BINARY
BC_BASE_FORMAT
BC_POW
BC_UNARY_MATH
BC_DEG_RAD
BC_AGGREGATE
BC_ARRAY_TRANSFORM
BC_REPEAT
BC_RANGE
BC_SORTBY
BC_RATIO
BC_FACTORIAL
BC_FACTORINT
BC_MOD
BC_TIME_UNIT
BC_POLAR_CART
BC_LOG
BC_UNKNOWN
end enum
enum BuiltinHintKind
BHK_NONE = 0
BHK_EMPTY_PAR
BHK_MIN_MAX
BHK_DOTDOTDOT
BHK_VALUE_POWER
BHK_Y_X
BHK_ANGLE
BHK_VALUE
BHK_VALUE_BASE
BHK_N
BHK_VALUE_DIVISOR
BHK_VALUE_MIN_MAX
BHK_X_Y
BHK_A_B
BHK_N_R
BHK_X_N
BHK_X
BHK_START_STOP_STEP
BHK_ARRAY_FUNC
end enum
type ScalarValue
scalarStorageKind as ScalarStorageKind
'' Do not read ``flags`` for exact-int or render-rational policy; use ScalarHas* / ScalarExact* getters.
flags as UInteger
scalar as Double
'' Numerator for ``SVF_RENDER_RATIONAL`` and exact integers; use getters, not direct reads, in eval paths.
exactInt64 as LongInt
'' Denominator for ``SVF_RENDER_RATIONAL`` and exact uintegers; use getters, not direct reads, in eval paths.
exactUInt64 as ULongInt
imag as Double
'' Imaginary numerator; use ScalarImag* getters (``SVF_IMAG_RENDER_RATIONAL`` uses imag exact fields).
imagExactInt64 as LongInt
imagExactUInt64 as ULongInt
declare property exactInt64Valid() as Boolean
declare property exactInt64Valid(byval v as Boolean)
declare property exactUInt64Valid() as Boolean
declare property exactUInt64Valid(byval v as Boolean)
declare property decScientificPow63High() as Boolean
declare property decScientificPow63High(byval v as Boolean)
end type
type EvalValue
kind as ValueKind
flags as UInteger
scalarValue as ScalarValue
arr(any) as ScalarValue
funcRefName as String
lambdaParams(any) as String
lambdaBody as String
sortbyKeyErrorCol as Integer
sortbyKeyBodyErrorCol as Integer
declare property renderBase() as Integer ' 0=decimal, 16=hex, 8=octal, 2=binary
declare property renderBase(byval v as Integer)
' uhex/uoct/ubin: two's complement as unsigned; hex/oct/bin: signed magnitude for negatives
declare property scalarStorageKind() as Integer
declare property scalarStorageKind(byval v as Integer)
declare property scalar() byref as Double
declare property scalar(byval v as Double)
declare property exactInt64Valid() as Boolean
declare property exactInt64Valid(byval v as Boolean)
declare property exactInt64() byref as LongInt
declare property exactInt64(byval v as LongInt)
declare property exactUInt64Valid() as Boolean
declare property exactUInt64Valid(byval v as Boolean)
declare property exactUInt64() byref as ULongInt
declare property exactUInt64(byval v as ULongInt)
declare property expandArgs() as Boolean
declare property expandArgs(byval v as Boolean)
declare property renderUnsigned() as Boolean
declare property renderUnsigned(byval v as Boolean)
end type
type DoubleBits
union
d as Double
u as ULongInt
end union
end type
declare function ScalarHasRenderRational(byref sv as ScalarValue) as Boolean
declare function ScalarHasImagRenderRational(byref sv as ScalarValue) as Boolean
declare function ScalarExactInt64Valid(byref sv as ScalarValue) as Boolean
declare function ScalarExactUInt64Valid(byref sv as ScalarValue) as Boolean
declare function ScalarImagExactInt64Valid(byref sv as ScalarValue) as Boolean
declare function ScalarImagExactUInt64Valid(byref sv as ScalarValue) as Boolean
declare function ScalarImagExactMetadataMatchesFloat(byref sv as ScalarValue) as Boolean
declare sub ScalarClearCartesianRenderExact(byref sv as ScalarValue)
declare sub ScalarApplyExactInt64Part(byref sv as ScalarValue, byval imagPart as Boolean, byval n as LongInt)
declare sub ScalarApplyReducedRationalPart(byref sv as ScalarValue, byval imagPart as Boolean, byval num as LongInt, byval den as ULongInt)
declare sub RawCartesianAssignReducedRational(byval num as LongInt, byval den as ULongInt, byref outC as RawCartesianScalar)
declare function TryGetExactInt64FromDouble(byval n as Double, byref outV as LongInt) as Boolean
declare sub ScalarRepairExactMetadata(byref sv as ScalarValue)
declare function ScalarNumericReal(byref sv as ScalarValue) as Double
declare function ScalarNumericImag(byref sv as ScalarValue) as Double
declare sub ScalarSetExactUInt64Valid(byref sv as ScalarValue, byval v as Boolean)
declare sub ScalarSetExactInt64Valid(byref sv as ScalarValue, byval v as Boolean)
declare sub ScalarSyncExactInt64WithUIntMirror(byref sv as ScalarValue, byval n as LongInt)
declare sub ScalarSyncExactUInt64WithIntMirror(byref sv as ScalarValue, byval n as ULongInt)
declare sub ScalarSyncImagExactInt64WithUIntMirror(byref sv as ScalarValue, byval n as LongInt)
declare sub ValueSetArrayFromScalarValues(byref outV as EvalValue, vals() as ScalarValue)
declare function GcdULong(byval a as ULongInt, byval b as ULongInt) as ULongInt
declare function TryPowULong(byval baseV as ULongInt, byval expV as ULongInt, byref outV as ULongInt) as Boolean
property ScalarValue.exactInt64Valid() as Boolean
return ScalarExactInt64Valid(this)
end property
property ScalarValue.exactInt64Valid(byval v as Boolean)
ScalarSetExactInt64Valid(this, v)
end property
property ScalarValue.exactUInt64Valid() as Boolean
return ScalarExactUInt64Valid(this)
end property
property ScalarValue.exactUInt64Valid(byval v as Boolean)
if v then
this.flags or= SVF_EXACT_UINT64_VALID
else
this.flags and= not CUInt(SVF_EXACT_UINT64_VALID)
end if
end property
property ScalarValue.decScientificPow63High() as Boolean
return (this.flags and SVF_DEC_SCI_POW63_HIGH) <> 0
end property
property ScalarValue.decScientificPow63High(byval v as Boolean)
if v then
this.flags or= SVF_DEC_SCI_POW63_HIGH
else
this.flags and= not CUInt(SVF_DEC_SCI_POW63_HIGH)
end if
end property
property EvalValue.scalarStorageKind() as Integer
return CInt(this.scalarValue.scalarStorageKind)
end property
property EvalValue.scalarStorageKind(byval v as Integer)
this.scalarValue.scalarStorageKind = v
end property
property EvalValue.scalar() byref as Double
return this.scalarValue.scalar
end property
property EvalValue.scalar(byval v as Double)
this.scalarValue.scalar = v
end property
property EvalValue.exactInt64Valid() as Boolean
return this.scalarValue.exactInt64Valid
end property
property EvalValue.exactInt64Valid(byval v as Boolean)
this.scalarValue.exactInt64Valid = v
end property
property EvalValue.exactInt64() byref as LongInt
return this.scalarValue.exactInt64
end property
property EvalValue.exactInt64(byval v as LongInt)
this.scalarValue.exactInt64 = v
end property
property EvalValue.exactUInt64Valid() as Boolean
return this.scalarValue.exactUInt64Valid
end property
property EvalValue.exactUInt64Valid(byval v as Boolean)
this.scalarValue.exactUInt64Valid = v
end property
property EvalValue.exactUInt64() byref as ULongInt
return this.scalarValue.exactUInt64
end property
property EvalValue.exactUInt64(byval v as ULongInt)
this.scalarValue.exactUInt64 = v
end property
property EvalValue.renderBase() as Integer
dim raw as UInteger = (this.flags and EVF_RENDER_BASE_MASK) shr EVF_RENDER_BASE_SHIFT
if raw = 0 then return 10
return CInt(raw)
end property
property EvalValue.renderBase(byval v as Integer)
this.flags and= not CUInt(EVF_RENDER_BASE_MASK)
this.flags or= (CUInt(v and &hFF) shl EVF_RENDER_BASE_SHIFT)
end property
property EvalValue.expandArgs() as Boolean
return (this.flags and EVF_EXPAND_ARGS) <> 0
end property
property EvalValue.expandArgs(byval v as Boolean)
if v then
this.flags or= EVF_EXPAND_ARGS
else
this.flags and= not CUInt(EVF_EXPAND_ARGS)
end if
end property
property EvalValue.renderUnsigned() as Boolean
return (this.flags and EVF_RENDER_UNSIGNED) <> 0
end property
property EvalValue.renderUnsigned(byval v as Boolean)
if v then
this.flags or= EVF_RENDER_UNSIGNED
else
this.flags and= not CUInt(EVF_RENDER_UNSIGNED)
end if
end property
type VarEntry
name as String
value as EvalValue
end type
type FuncEntry
name as String
params(any) as String
expr as String
end type
#include once "MathParserFactorInt.bas"
#define __FB_FUNC_VARS_OVERRIDE_GLOBALS__ 1
'
' With a fixed formal probe of 0, `f(x)=1%x` fails validation (mod 0).
' With 1, `f(x)=1%(x-1)` can fail (again, mode 0).
' When this define is enabled, each formal parameter is given the value
' of scalar variable `_` during UDF body validation if `_` exists,
' otherwise the default probe 1.
' Example: `_=10; f(x)=1%(x-1)` passes the validation.
' Runtime calls still use real arguments.
'
' Without this define, `x=1; f(x)=1%x` and `x=2; f(x)=1%(x-1)` work by
' seeding x during validation when a global variable shares a formal name.
' A name is either a user function or a variable: defining f(...) removes variable f;
' assigning to x removes user function x (see SetUserFunction / assignment path).
dim shared variables() as VarEntry
dim shared userFunctions() as FuncEntry
dim shared pStream as ZString ptr
dim shared parseError as Integer
dim shared arrayIndexBracketDepth as Integer = 0
dim shared wasPercentage as Boolean
dim shared lastErrorText as String
dim shared lastRawResultValid as Boolean = FALSE
dim shared lastRawResult as RawResult
dim shared unknownVarsText as String
dim shared unknownFuncsText as String
#ifdef __FB_FUNC_VARS_OVERRIDE_GLOBALS__
dim shared functionVariableNames() as String
dim shared functionVariableCount as Integer
#endif
dim shared evalDepth as Integer
const UDF_CALL_STACK_MAX as Integer = 128
dim shared udfCallStack(0 to UDF_CALL_STACK_MAX - 1) as String
dim shared udfCallStackSp as Integer
dim shared validatingUserFunctionName as String
' suppressBareFunctionTailHint: skip bare-function tail hints when ';' context was lost.
' Path A: whole bare name + ';' (e.g. cos;) -> unexpected token in TryEvaluateTopLevelStatements.
' Path B: ';' still in pStream -> TryHandleBareBuiltinOrUdfIdent checks pStream[0].
' Path C: trailing ';' stripped or stmt split without ';' -> set flag from normalize return or caller.
dim shared suppressBareFunctionTailHint as Boolean
dim shared exprStart as ZString ptr
dim shared errorBaseCol as Integer
dim shared rootInputExpr as String
dim shared sortbyKeyParseErrorCol as Integer = 0
dim shared sortbyKeyBodyParseErrorCol as Integer = 0
dim shared sortbyLambdaEvalBodyErrorCol as Integer = 0
dim shared Parser_ShowErrorLine as Boolean = FALSE
dim shared Parser_SupportComplexNumbers as Boolean = FALSE
dim shared Parser_SupportTimeValues as Boolean = TRUE
dim shared Parser_SupportLambdaFunctions as Boolean = TRUE
private function MakeNaN() as Double
return 0.0 / 0.0
end function
private function IsNaNValue(byval d as Double) as Boolean
return (_isnan(d) <> 0)
end function
private function IsInfValue(byval d as Double) as Boolean
if _isnan(d) <> 0 then return FALSE
dim infV as Double = 1.0 / 0.0
return abs(d) = infV
end function
private function IsNonFiniteValue(byval d as Double) as Boolean
return IsNaNValue(d) orelse IsInfValue(d)
end function
private function RoundHalfUpDoubleToLongInt(byval x as Double) as LongInt
if IsNonFiniteValue(x) then return 0
if x >= 0 then
return CLngInt(Int(x + 0.5))
end if
return -CLngInt(Int(-x + 0.5))
end function
private function ULongIntToString(byval x as ULongInt) as String
if x = 0 then return "0"
dim s as String = ""
while x > 0
s = chr(48 + (x mod 10)) + s
x \= 10
wend
return s
end function
private function Pad2Digits(byval n as LongInt) as String
if n < 0 then n = 0
if n >= 100 then return ltrim(str(n))
if n >= 10 then return chr(48 + n \ 10) & chr(48 + n mod 10)
return "0" & chr(48 + n mod 10)
end function
private function ScalarIsTime(byref sv as ScalarValue) as Boolean
if Parser_SupportTimeValues = FALSE then return FALSE
return (sv.scalarStorageKind = SSK_TIME)
end function
private function TimeTotalMsFromScalarValue(byref sv as ScalarValue) as LongInt
return sv.exactInt64
end function
private function FormatTimeCanonicalFromMs(byval totalMs as LongInt) as String
dim neg as Boolean = (totalMs < 0)
dim rU as ULongInt
if neg then
if totalMs = FB_I64_MIN then
rU = CULngInt(FB_I64_MIN_MAG_U)
else
rU = CULngInt(-totalMs)
end if
else
rU = CULngInt(totalMs)
end if
dim msPart as LongInt = CLngInt(rU mod 1000ull)
rU = rU \ 1000ull
dim sPart as LongInt = CLngInt(rU mod 60ull)
rU = rU \ 60ull
dim mPart as LongInt = CLngInt(rU mod 60ull)
rU = rU \ 60ull
dim hPart as LongInt = CLngInt(rU mod 24ull)
rU = rU \ 24ull
dim dPart as ULongInt = rU
dim body as String
if dPart > 0ull then
body = ULongIntToString(dPart) & ":" & Pad2Digits(hPart) & ":" & Pad2Digits(mPart) & ":" & Pad2Digits(sPart)
elseif hPart > 0 then
body = Pad2Digits(hPart) & ":" & Pad2Digits(mPart) & ":" & Pad2Digits(sPart)
else
body = Pad2Digits(mPart) & ":" & Pad2Digits(sPart)
end if
if msPart <> 0 then
body &= "." & chr(48 + (msPart \ 100)) & chr(48 + ((msPart \ 10) mod 10)) & chr(48 + (msPart mod 10))
end if
if neg then return "-" & body
return body
end function
private sub ValueSetTimeMs(byref v as EvalValue, byval totalMs as LongInt)
v.kind = VK_SCALAR
v.scalarStorageKind = SSK_TIME
v.scalar = CDbl(totalMs) / 1000.0
v.exactInt64Valid = FALSE
v.exactInt64 = totalMs
v.exactUInt64Valid = FALSE
v.exactUInt64 = 0
v.expandArgs = FALSE
v.renderBase = 10
v.renderUnsigned = FALSE
erase v.arr
end sub
private function TryAddTimeMsChecked(byval a as LongInt, byval b as LongInt, byref outMs as LongInt) as Boolean
dim t as Double = CDbl(a) + CDbl(b)
if t < CDbl(FB_I64_MIN) orelse t > CDbl(FB_I64_MAX) then return FALSE
outMs = RoundHalfUpDoubleToLongInt(t)
return TRUE
end function
private function TrySubTimeMsChecked(byval a as LongInt, byval b as LongInt, byref outMs as LongInt) as Boolean
dim t as Double = CDbl(a) - CDbl(b)
if t < CDbl(FB_I64_MIN) orelse t > CDbl(FB_I64_MAX) then return FALSE
outMs = RoundHalfUpDoubleToLongInt(t)
return TRUE
end function
private function ScalarHasRenderRational(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_RENDER_RATIONAL) <> 0
end function
private function ScalarHasImagRenderRational(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_IMAG_RENDER_RATIONAL) <> 0
end function
private function ScalarExactInt64MetadataValid(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_EXACT_INT64_VALID) <> 0
end function
private function ScalarExactUInt64MetadataValid(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_EXACT_UINT64_VALID) <> 0
end function
private function ScalarImagExactInt64MetadataValid(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_IMAG_EXACT_INT64_VALID) <> 0
end function
private function ScalarImagExactUInt64MetadataValid(byref sv as ScalarValue) as Boolean
return (sv.flags and SVF_IMAG_EXACT_UINT64_VALID) <> 0
end function
private function ScalarImagExactInt64Valid(byref sv as ScalarValue) as Boolean
if ScalarHasImagRenderRational(sv) then return FALSE
return ScalarImagExactInt64MetadataValid(sv)
end function
private function ScalarImagExactUInt64Valid(byref sv as ScalarValue) as Boolean
if ScalarHasImagRenderRational(sv) then return FALSE
return ScalarImagExactUInt64MetadataValid(sv)
end function
private function ScalarHasNonzeroImaginaryPart(byref sv as ScalarValue) as Boolean
' NaN comparisons are not reliable for "nonzero" checks, and we must not
' normalize complex values with NaN/Inf imaginary components into pure-real.
if IsNaNValue(sv.imag) then return TRUE
if IsInfValue(sv.imag) then return TRUE