counted-float 1.0.3__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {counted_float-1.0.3 → counted_float-1.0.4}/.gitignore +4 -1
- {counted_float-1.0.3 → counted_float-1.0.4}/PKG-INFO +34 -8
- {counted_float-1.0.3 → counted_float-1.0.4}/README.md +33 -7
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/_counted_float.py +93 -8
- {counted_float-1.0.3 → counted_float-1.0.4}/pyproject.toml +1 -1
- {counted_float-1.0.3 → counted_float-1.0.4}/LICENSE +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/_cli.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/counted_float/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/counted_float/_counted_float_benchmark.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/flops/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/flops/_array_generator.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/flops/_flops_benchmark_suite.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/flops/_flops_micro_benchmark.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/micro/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/micro/_micro_benchmark.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/compatibility/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/compatibility/_numba.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/_builtin_data.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/_context_managers.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/_global_counter.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/config/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/config/_config.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/config/_defaults.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_base.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flop_counts.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flop_type.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flop_weights.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_meta_data.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_result.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_type.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_instruction_latencies.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_micro_benchmark_result.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_cpu_freq.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_formatting.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_geo_mean.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_latency.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_missing_data.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_rounding.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/utils/_timer.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/benchmarking/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/config/__init__.py +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/benchmarks/apple_m1_github_actions.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/benchmarks/apple_m3_max_mbp16.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/benchmarks/apple_m3_mba15.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/benchmarks/aws_graviton_2_neoverse_n1_ec2_m6g_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/benchmarks/aws_graviton_3_neoverse_v1_ec2_m7g_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_cortex_a76.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_cortex_x1.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_neoverse_n1.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_neoverse_v1.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/benchmarks/aws_graviton_4_neoverse_v2_ec2_m8g_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/benchmarks/azure_cobalt_100_neoverse_n2_github_actions.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_cortex_x2.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_cortex_x3.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_neoverse_n2.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_neoverse_v2.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/benchmarks/apple_m4_pro_mbp16.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_cortex_x4.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_cortex_x925.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_neoverse_v3.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2017_zen1/benchmarks/amd_ryzen_1700x.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2017_zen1/other/analysis_uops_info_zen1+.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2020_zen3/benchmark/amd_epyc_7763_linux_github.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2020_zen3/benchmark/amd_epyc_7763_windows_github.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2020_zen3/other/analysis_agner_fog_r7_5800x.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2020_zen3/other/analysis_uops_info_zen3.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2022_zen4/benchmark/amd_epyc_9r14_ec2_m7a_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2022_zen4/other/analysis_agner_fog_r9_7900x.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2022_zen4/other/analysis_uops_info_zen4.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2022_zen4/other/specs_amd.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2024_zen5/benchmark/amd_epyc_9r45_ec2_m8a_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2024_zen5/other/analysis_agner_fog_r7_9800x3d.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/amd/2024_zen5/other/specs_amd.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2017_coffee_lake_gen_8/benchmarks/intel_i7_8550U_windows.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2017_coffee_lake_gen_8/benchmarks/intel_i7_8700B_macos_github_actions.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2017_coffee_lake_gen_8/other/analysis_agner_fog_coffee_lake.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2017_coffee_lake_gen_8/other/analysis_uops_info_coffee_lake.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2019_sunny_cove_gen_10/benchmarks/intel_xeon_8375c_ice_lake_ec2_m6i_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2019_sunny_cove_gen_10/other/analysis_agner_fog_ice_lake.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2019_sunny_cove_gen_10/other/analysis_uops_info_ice_lake.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2019_sunny_cove_gen_10/other/analysis_uops_info_tiger_lake.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2021_golden_cove_gen_12/benchmarks/intel_xeon_8488c_sapphire_rapids_ec2_m7i_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2021_golden_cove_gen_12/other/analysis_uops_info_alder_lake_p.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2021_golden_cove_gen_12/other/specs_intel.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2022_raptor_cove_gen_13_14/benchmarks/intel_xeon_8559c_emerald_rapids_ec2_i7i_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2022_raptor_cove_gen_13_14/other/specs_intel.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2023_redwood_cove_ultra_1/benchmarks/intel_xeon_6975p_granite_rapids_ec2_m8i_xlarge.json +0 -0
- {counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/x86/intel/2023_redwood_cove_ultra_1/other/specs_intel.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: counted-float
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Count floating-point operations in Python code & benchmark relative flop costs.
|
|
5
5
|
Project-URL: Source, https://github.com/bertpl/counted-float
|
|
6
6
|
Project-URL: ChangeLog, https://github.com/bertpl/counted-float/blob/main/CHANGELOG.md
|
|
@@ -20,9 +20,9 @@ Requires-Dist: numba>=0.50; extra == 'numba'
|
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
|
|
22
22
|

|
|
23
|
-

|
|
24
|
+

|
|
25
|
+

|
|
26
26
|
|
|
27
27
|
# counted-float
|
|
28
28
|
|
|
@@ -90,7 +90,33 @@ s = math.sqrt(cf1) # s = CountedFloat(0.9)
|
|
|
90
90
|
is_float = isinstance(s, float) # True
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
### The counting model: what gets counted and why
|
|
94
|
+
|
|
95
|
+
The counting model is a contract with two sides:
|
|
96
|
+
|
|
97
|
+
- **Your side:** wrap every *runtime input* of the algorithm you want to measure in `CountedFloat`
|
|
98
|
+
at its boundary. Contagion does the rest — everything derived from those inputs stays counted
|
|
99
|
+
automatically.
|
|
100
|
+
- **The library's side:** count every FLOP that a compiled (C/Rust/...) port of your algorithm
|
|
101
|
+
would execute *on data derived from those inputs*.
|
|
102
|
+
|
|
103
|
+
From this contract follows a clean rule for everything else: **constants are free.** Any plain
|
|
104
|
+
float encountered mid-computation is, by the contract, not an input — so it must be a constant of
|
|
105
|
+
the algorithm (a literal, a coefficient, a tolerance), and operations purely among constants are
|
|
106
|
+
work a compiled port would fold at compile time or precompute. This is why e.g. `math.sqrt(3)`
|
|
107
|
+
counts nothing: the port ships `sqrt(3)` as a precomputed constant.
|
|
108
|
+
|
|
109
|
+
The library detects constants through two mechanisms, applying the same rule:
|
|
110
|
+
|
|
111
|
+
- **Unwrapped values** (plain floats): constants by the wrapping contract, as above.
|
|
112
|
+
- **`int` operands**: evidence of a *hardcoded* constant — ints don't fall out of floating-point
|
|
113
|
+
computations, so an int operand almost certainly appears literally in your source. This enables
|
|
114
|
+
counting the strength reductions a compiled port would apply: `x**2` counts MUL (i.e. `x*x`),
|
|
115
|
+
`2**x` counts EXP2, `math.log(x, 10)` counts LOG10 — while `x**2.0`, with a float that *could*
|
|
116
|
+
be a runtime value, conservatively counts a generic POW.
|
|
117
|
+
|
|
118
|
+
The flip side: an unwrapped runtime input is invisible to the counter — that is a wrapping error
|
|
119
|
+
at your algorithm's boundary, not something the library can detect. When in doubt, wrap.
|
|
94
120
|
|
|
95
121
|
Once we use the `CountedFloat` class, we can use the available context managers to count the number of
|
|
96
122
|
flops performed by `CountedFloat` objects.
|
|
@@ -636,21 +662,21 @@ This appendix provides detailed information about how each floating-point operat
|
|
|
636
662
|
- Relevant CPU instructions
|
|
637
663
|
- **ARM:** (software)
|
|
638
664
|
- **x86:** (software)
|
|
639
|
-
- **Counted Python operations:** `math.log(x)` for `CountedFloat`
|
|
665
|
+
- **Counted Python operations:** `math.log(x)` for `CountedFloat`; `math.log(x, base)` for `CountedFloat` decomposes per the constant-detection heuristic (int base 2/10 -> LOG2/LOG10; other int base -> LOG+MUL; float base -> LOG per counted operand + DIV)
|
|
640
666
|
- **Not counted:** `numpy.log`, log on non-CountedFloat
|
|
641
667
|
|
|
642
668
|
### FlopType.LOG2 (`log2(x)`)
|
|
643
669
|
- Relevant CPU instructions
|
|
644
670
|
- **ARM:** (software)
|
|
645
671
|
- **x86:** (software)
|
|
646
|
-
- **Counted Python operations:** `math.log2(x)` for `CountedFloat`
|
|
672
|
+
- **Counted Python operations:** `math.log2(x)` for `CountedFloat`; `math.log(x, 2)` (int base) for `CountedFloat`
|
|
647
673
|
- **Not counted:** `numpy.log2`, log2 on non-CountedFloat
|
|
648
674
|
|
|
649
675
|
### FlopType.LOG10 (`log10(x)`)
|
|
650
676
|
- Relevant CPU instructions
|
|
651
677
|
- **ARM:** (software)
|
|
652
678
|
- **x86:** (software)
|
|
653
|
-
- **Counted Python operations:** `math.log10(x)` for `CountedFloat`
|
|
679
|
+
- **Counted Python operations:** `math.log10(x)` for `CountedFloat`; `math.log(x, 10)` (int base) for `CountedFloat`
|
|
654
680
|
- **Not counted:** `numpy.log10`, log10 on non-CountedFloat
|
|
655
681
|
|
|
656
682
|
### FlopType.POW (`x^y`)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|

|
|
2
|
-

|
|
3
|
+

|
|
4
|
+

|
|
5
5
|
|
|
6
6
|
# counted-float
|
|
7
7
|
|
|
@@ -69,7 +69,33 @@ s = math.sqrt(cf1) # s = CountedFloat(0.9)
|
|
|
69
69
|
is_float = isinstance(s, float) # True
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
### The counting model: what gets counted and why
|
|
73
|
+
|
|
74
|
+
The counting model is a contract with two sides:
|
|
75
|
+
|
|
76
|
+
- **Your side:** wrap every *runtime input* of the algorithm you want to measure in `CountedFloat`
|
|
77
|
+
at its boundary. Contagion does the rest — everything derived from those inputs stays counted
|
|
78
|
+
automatically.
|
|
79
|
+
- **The library's side:** count every FLOP that a compiled (C/Rust/...) port of your algorithm
|
|
80
|
+
would execute *on data derived from those inputs*.
|
|
81
|
+
|
|
82
|
+
From this contract follows a clean rule for everything else: **constants are free.** Any plain
|
|
83
|
+
float encountered mid-computation is, by the contract, not an input — so it must be a constant of
|
|
84
|
+
the algorithm (a literal, a coefficient, a tolerance), and operations purely among constants are
|
|
85
|
+
work a compiled port would fold at compile time or precompute. This is why e.g. `math.sqrt(3)`
|
|
86
|
+
counts nothing: the port ships `sqrt(3)` as a precomputed constant.
|
|
87
|
+
|
|
88
|
+
The library detects constants through two mechanisms, applying the same rule:
|
|
89
|
+
|
|
90
|
+
- **Unwrapped values** (plain floats): constants by the wrapping contract, as above.
|
|
91
|
+
- **`int` operands**: evidence of a *hardcoded* constant — ints don't fall out of floating-point
|
|
92
|
+
computations, so an int operand almost certainly appears literally in your source. This enables
|
|
93
|
+
counting the strength reductions a compiled port would apply: `x**2` counts MUL (i.e. `x*x`),
|
|
94
|
+
`2**x` counts EXP2, `math.log(x, 10)` counts LOG10 — while `x**2.0`, with a float that *could*
|
|
95
|
+
be a runtime value, conservatively counts a generic POW.
|
|
96
|
+
|
|
97
|
+
The flip side: an unwrapped runtime input is invisible to the counter — that is a wrapping error
|
|
98
|
+
at your algorithm's boundary, not something the library can detect. When in doubt, wrap.
|
|
73
99
|
|
|
74
100
|
Once we use the `CountedFloat` class, we can use the available context managers to count the number of
|
|
75
101
|
flops performed by `CountedFloat` objects.
|
|
@@ -615,21 +641,21 @@ This appendix provides detailed information about how each floating-point operat
|
|
|
615
641
|
- Relevant CPU instructions
|
|
616
642
|
- **ARM:** (software)
|
|
617
643
|
- **x86:** (software)
|
|
618
|
-
- **Counted Python operations:** `math.log(x)` for `CountedFloat`
|
|
644
|
+
- **Counted Python operations:** `math.log(x)` for `CountedFloat`; `math.log(x, base)` for `CountedFloat` decomposes per the constant-detection heuristic (int base 2/10 -> LOG2/LOG10; other int base -> LOG+MUL; float base -> LOG per counted operand + DIV)
|
|
619
645
|
- **Not counted:** `numpy.log`, log on non-CountedFloat
|
|
620
646
|
|
|
621
647
|
### FlopType.LOG2 (`log2(x)`)
|
|
622
648
|
- Relevant CPU instructions
|
|
623
649
|
- **ARM:** (software)
|
|
624
650
|
- **x86:** (software)
|
|
625
|
-
- **Counted Python operations:** `math.log2(x)` for `CountedFloat`
|
|
651
|
+
- **Counted Python operations:** `math.log2(x)` for `CountedFloat`; `math.log(x, 2)` (int base) for `CountedFloat`
|
|
626
652
|
- **Not counted:** `numpy.log2`, log2 on non-CountedFloat
|
|
627
653
|
|
|
628
654
|
### FlopType.LOG10 (`log10(x)`)
|
|
629
655
|
- Relevant CPU instructions
|
|
630
656
|
- **ARM:** (software)
|
|
631
657
|
- **x86:** (software)
|
|
632
|
-
- **Counted Python operations:** `math.log10(x)` for `CountedFloat`
|
|
658
|
+
- **Counted Python operations:** `math.log10(x)` for `CountedFloat`; `math.log(x, 10)` (int base) for `CountedFloat`
|
|
633
659
|
- **Not counted:** `numpy.log10`, log10 on non-CountedFloat
|
|
634
660
|
|
|
635
661
|
### FlopType.POW (`x^y`)
|
|
@@ -182,7 +182,15 @@ class CountedFloat(float):
|
|
|
182
182
|
return CountedFloat(super().__rtruediv__(other))
|
|
183
183
|
|
|
184
184
|
def __pow__(self, other) -> CountedFloat:
|
|
185
|
-
"""
|
|
185
|
+
"""
|
|
186
|
+
x**other
|
|
187
|
+
|
|
188
|
+
Counting heuristic: an `int` operand is taken as evidence of a hardcoded constant in the
|
|
189
|
+
source (ints don't fall out of floating-point computations), so `x**2` counts as MUL —
|
|
190
|
+
the strength reduction (x*x) a compiled port would apply. A float operand may just as well
|
|
191
|
+
be a runtime variable that happens to hold that value, where a port would compile a
|
|
192
|
+
generic pow, so `x**2.0` counts as POW.
|
|
193
|
+
"""
|
|
186
194
|
if isinstance(other, int) and other == 2:
|
|
187
195
|
GLOBAL_COUNTER.incr_mul() # x^2 = x*x
|
|
188
196
|
else:
|
|
@@ -192,7 +200,14 @@ class CountedFloat(float):
|
|
|
192
200
|
return CountedFloat(super().__pow__(other))
|
|
193
201
|
|
|
194
202
|
def __rpow__(self, other) -> CountedFloat:
|
|
195
|
-
"""
|
|
203
|
+
"""
|
|
204
|
+
other**x
|
|
205
|
+
|
|
206
|
+
Same constant-detection heuristic as __pow__, applied to the base: an `int` base 2 or 10
|
|
207
|
+
is taken as a hardcoded constant, counting as EXP2 / EXP10 (the strength reduction a
|
|
208
|
+
compiled port would apply); a float base may be a runtime variable, so it counts as
|
|
209
|
+
generic POW.
|
|
210
|
+
"""
|
|
196
211
|
if isinstance(other, int) and other == 2:
|
|
197
212
|
GLOBAL_COUNTER.incr_exp2()
|
|
198
213
|
elif isinstance(other, int) and other == 10:
|
|
@@ -214,10 +229,15 @@ original_math_log2 = math.log2
|
|
|
214
229
|
original_math_log10 = math.log10
|
|
215
230
|
original_math_exp = math.exp
|
|
216
231
|
original_math_exp2 = math.exp2
|
|
232
|
+
original_math_pow = math.pow
|
|
217
233
|
original_math_sin = math.sin
|
|
218
234
|
original_math_cos = math.cos
|
|
219
235
|
original_math_tan = math.tan
|
|
220
236
|
|
|
237
|
+
# sentinel for math_log's optional base argument; the stdlib signature is math.log(x[, base]),
|
|
238
|
+
# where omitting base is not the same as passing any real value (and None is rejected)
|
|
239
|
+
_NO_BASE = object()
|
|
240
|
+
|
|
221
241
|
|
|
222
242
|
def math_sqrt(x: float) -> float | CountedFloat:
|
|
223
243
|
if isinstance(x, CountedFloat):
|
|
@@ -235,12 +255,50 @@ def math_cbrt(x: float) -> float | CountedFloat:
|
|
|
235
255
|
return original_math_cbrt(x)
|
|
236
256
|
|
|
237
257
|
|
|
238
|
-
def math_log(x: float) -> float | CountedFloat:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
258
|
+
def math_log(x: float, base=_NO_BASE) -> float | CountedFloat:
|
|
259
|
+
"""
|
|
260
|
+
Patched math.log: stdlib contract (optional base), with flop classification for the base
|
|
261
|
+
following the same constant-detection heuristic as CountedFloat.__pow__ / __rpow__
|
|
262
|
+
(int operand = hardcoded constant in the source):
|
|
263
|
+
- base omitted -> LOG
|
|
264
|
+
- base int 2 / 10 -> LOG2 / LOG10 (a compiled port calls log2/log10 directly)
|
|
265
|
+
- base other int -> LOG + MUL (a port computes log(x) * C, with C = 1/log(base) folded
|
|
266
|
+
at compile time)
|
|
267
|
+
- base float -> a port computes log(x)/log(base): LOG per CountedFloat operand + DIV
|
|
268
|
+
As everywhere in the counting model, only operations touching CountedFloat values are counted:
|
|
269
|
+
any runtime input to the counted algorithm should itself be a CountedFloat; whatever remains a
|
|
270
|
+
plain float is by definition not part of the core algorithm and/or precomputable.
|
|
271
|
+
"""
|
|
272
|
+
if base is _NO_BASE:
|
|
273
|
+
if isinstance(x, CountedFloat):
|
|
274
|
+
GLOBAL_COUNTER.incr_log()
|
|
275
|
+
return CountedFloat(original_math_log(x))
|
|
276
|
+
else:
|
|
277
|
+
return original_math_log(x)
|
|
242
278
|
else:
|
|
243
|
-
|
|
279
|
+
# computed first: raises per stdlib contract before anything is counted
|
|
280
|
+
result = original_math_log(x, base)
|
|
281
|
+
if isinstance(base, int) and base == 2:
|
|
282
|
+
if isinstance(x, CountedFloat):
|
|
283
|
+
GLOBAL_COUNTER.incr_log2()
|
|
284
|
+
elif isinstance(base, int) and base == 10:
|
|
285
|
+
if isinstance(x, CountedFloat):
|
|
286
|
+
GLOBAL_COUNTER.incr_log10()
|
|
287
|
+
elif isinstance(base, int):
|
|
288
|
+
if isinstance(x, CountedFloat):
|
|
289
|
+
GLOBAL_COUNTER.incr_log()
|
|
290
|
+
GLOBAL_COUNTER.incr_mul()
|
|
291
|
+
else:
|
|
292
|
+
if isinstance(x, CountedFloat):
|
|
293
|
+
GLOBAL_COUNTER.incr_log()
|
|
294
|
+
if isinstance(base, CountedFloat):
|
|
295
|
+
GLOBAL_COUNTER.incr_log()
|
|
296
|
+
if isinstance(x, CountedFloat) or isinstance(base, CountedFloat):
|
|
297
|
+
GLOBAL_COUNTER.incr_div()
|
|
298
|
+
if isinstance(x, CountedFloat) or isinstance(base, CountedFloat):
|
|
299
|
+
return CountedFloat(result)
|
|
300
|
+
else:
|
|
301
|
+
return result
|
|
244
302
|
|
|
245
303
|
|
|
246
304
|
def math_log2(x: float) -> float | CountedFloat:
|
|
@@ -276,7 +334,34 @@ def math_exp2(x: float) -> float | CountedFloat:
|
|
|
276
334
|
|
|
277
335
|
|
|
278
336
|
def math_pow(x: float, y: float) -> float | CountedFloat:
|
|
279
|
-
|
|
337
|
+
"""
|
|
338
|
+
Patched math.pow: stdlib contract (always-float result, ValueError on domain errors), with
|
|
339
|
+
flop classification identical to the x**y form — including the constant-detection heuristic
|
|
340
|
+
documented on CountedFloat.__pow__ / __rpow__ (int operand = hardcoded constant).
|
|
341
|
+
"""
|
|
342
|
+
if isinstance(x, CountedFloat) or isinstance(y, CountedFloat):
|
|
343
|
+
# computed first: math.pow raises ValueError on domain errors (e.g. negative base with
|
|
344
|
+
# fractional exponent) and then nothing should be counted
|
|
345
|
+
result = original_math_pow(x, y)
|
|
346
|
+
if isinstance(x, CountedFloat):
|
|
347
|
+
if isinstance(y, int) and y == 2:
|
|
348
|
+
GLOBAL_COUNTER.incr_mul() # x^2 = x*x
|
|
349
|
+
else:
|
|
350
|
+
if isinstance(y, int):
|
|
351
|
+
GLOBAL_COUNTER.incr_i2f()
|
|
352
|
+
GLOBAL_COUNTER.incr_pow()
|
|
353
|
+
else:
|
|
354
|
+
if isinstance(x, int) and x == 2:
|
|
355
|
+
GLOBAL_COUNTER.incr_exp2()
|
|
356
|
+
elif isinstance(x, int) and x == 10:
|
|
357
|
+
GLOBAL_COUNTER.incr_exp10()
|
|
358
|
+
else:
|
|
359
|
+
if isinstance(x, int):
|
|
360
|
+
GLOBAL_COUNTER.incr_i2f()
|
|
361
|
+
GLOBAL_COUNTER.incr_pow()
|
|
362
|
+
return CountedFloat(result)
|
|
363
|
+
else:
|
|
364
|
+
return original_math_pow(x, y)
|
|
280
365
|
|
|
281
366
|
|
|
282
367
|
def math_sin(x: float) -> float | CountedFloat:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/flops/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/benchmarking/micro/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/_context_managers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/counting/config/_defaults.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_meta_data.py
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_result.py
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_flops_benchmark_type.py
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_instruction_latencies.py
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/_core/models/_micro_benchmark_result.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_cortex_a76.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_cortex_x1.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_neoverse_n1.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v8_x/specs/arm_neoverse_v1.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_cortex_x2.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_cortex_x3.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_neoverse_n2.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_0/specs/arm_neoverse_v2.json
RENAMED
|
File without changes
|
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_cortex_x4.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_cortex_x925.json
RENAMED
|
File without changes
|
{counted_float-1.0.3 → counted_float-1.0.4}/counted_float/data/arm/v9_2/specs/arm_neoverse_v3.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|