IsoSpecPy 2.5.0__py3-none-win32.whl

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.
Files changed (45) hide show
  1. IsoSpecPy/Advanced.py +32 -0
  2. IsoSpecPy/Distributions.py +93 -0
  3. IsoSpecPy/Formulas.py +71 -0
  4. IsoSpecPy/IsoSpec++/aligned_ptr.h +638 -0
  5. IsoSpecPy/IsoSpec++/allocator.h +69 -0
  6. IsoSpecPy/IsoSpec++/btrd.h +206 -0
  7. IsoSpecPy/IsoSpec++/composition.h +126 -0
  8. IsoSpecPy/IsoSpec++/conf.h +38 -0
  9. IsoSpecPy/IsoSpec++/cwrapper.h +271 -0
  10. IsoSpecPy/IsoSpec++/dirtyAllocator.h +58 -0
  11. IsoSpecPy/IsoSpec++/element_lookup.h +36 -0
  12. IsoSpecPy/IsoSpec++/element_tables.h +50 -0
  13. IsoSpecPy/IsoSpec++/fasta.h +70 -0
  14. IsoSpecPy/IsoSpec++/fasta_mods.h +70 -0
  15. IsoSpecPy/IsoSpec++/fixedEnvelopes.h +418 -0
  16. IsoSpecPy/IsoSpec++/isa_kernel_impl.h +192 -0
  17. IsoSpecPy/IsoSpec++/isa_kernels.h +172 -0
  18. IsoSpecPy/IsoSpec++/isoMath.h +121 -0
  19. IsoSpecPy/IsoSpec++/isoSpec++.h +801 -0
  20. IsoSpecPy/IsoSpec++/iso_simd.h +48 -0
  21. IsoSpecPy/IsoSpec++/marginalTrek++.h +614 -0
  22. IsoSpecPy/IsoSpec++/misc.h +229 -0
  23. IsoSpecPy/IsoSpec++/mman.h +67 -0
  24. IsoSpecPy/IsoSpec++/operators.h +150 -0
  25. IsoSpecPy/IsoSpec++/platform.h +180 -0
  26. IsoSpecPy/IsoSpec++/platform_incl.h +33 -0
  27. IsoSpecPy/IsoSpec++/pod_vector.h +400 -0
  28. IsoSpecPy/IsoSpec++/summator.h +118 -0
  29. IsoSpecPy/IsoSpec++/unimod.h +80 -0
  30. IsoSpecPy/IsoSpec++/unimod_support.h +2169 -0
  31. IsoSpecPy/IsoSpec++/unimod_table_data.h +1027 -0
  32. IsoSpecPy/IsoSpecPy.py +1088 -0
  33. IsoSpecPy/IsoSpecPyOld.py +290 -0
  34. IsoSpecPy/PeriodicTbl.py +51 -0
  35. IsoSpecPy/__init__.py +19 -0
  36. IsoSpecPy/__main__.py +25 -0
  37. IsoSpecPy/approximations.py +122 -0
  38. IsoSpecPy/confs_passthrough.py +16 -0
  39. IsoSpecPy/isoFFI.py +290 -0
  40. bin/IsoSpecCppPy.dll +0 -0
  41. isospecpy-2.5.0.dist-info/METADATA +220 -0
  42. isospecpy-2.5.0.dist-info/RECORD +45 -0
  43. isospecpy-2.5.0.dist-info/WHEEL +5 -0
  44. isospecpy-2.5.0.dist-info/licenses/LICENCE +35 -0
  45. lib/IsoSpecCppPy.lib +0 -0
@@ -0,0 +1,172 @@
1
+ /*
2
+ * Copyright (C) 2015-2020 Mateusz Łącki and Michał Startek.
3
+ *
4
+ * This file is part of IsoSpec.
5
+ *
6
+ * IsoSpec is free software: you can redistribute it and/or modify
7
+ * it under the terms of the Simplified ("2-clause") BSD licence.
8
+ *
9
+ * IsoSpec is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+ *
13
+ * You should have received a copy of the Simplified BSD Licence
14
+ * along with IsoSpec. If not, see <https://opensource.org/licenses/BSD-2-Clause>.
15
+ */
16
+
17
+ #pragma once
18
+
19
+ #include <cstddef>
20
+ #include "platform.h"
21
+ #include "iso_simd.h"
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Runtime ISA dispatch.
25
+ //
26
+ // A single binary can carry several builds of the two batched fill kernels --
27
+ // one per instruction-set level -- and pick the best one the CPU actually
28
+ // supports, at run time. This matters because the distributed builds have no
29
+ // -march at all (the PyPI wheel is compiled at the x86-64 baseline, so its
30
+ // vectors are 2 doubles wide), while the machines running them are mostly
31
+ // AVX2-or-better.
32
+ //
33
+ // Why it is built this way, and not the two obvious easier ways:
34
+ //
35
+ // * __attribute__((target(...))) / target_clones() cannot do it.
36
+ // std::experimental::simd fixes its ABI when the templates are instantiated,
37
+ // from the -march preprocessor macros; a target attribute applied afterwards
38
+ // changes only the *encoding*. Measured: fixed_size_simd<double,8> inside a
39
+ // target("avx512f") function on a baseline TU emits nothing but xmm, and
40
+ // native_simd<double> under target_clones still reports 2 lanes. So the
41
+ // levels have to be separate translation units, each with its own -march.
42
+ //
43
+ // * Those TUs must not include the library's own headers. A TU compiled at
44
+ // -march=x86-64-v4 emits VEX/EVEX code into the COMDAT copies of every
45
+ // inline and template function it instantiates, and the linker then picks
46
+ // one copy of each for the whole program -- by link order. Measured: the
47
+ // same two objects linked in the opposite order gave a surviving copy of a
48
+ // shared inline function using %zmm, reachable from baseline code paths,
49
+ // i.e. SIGILL on any CPU without AVX-512.
50
+ //
51
+ // Hence the interface below is deliberately POD-only: raw pointers and doubles,
52
+ // no IsoSpec types, nothing with a definition that could be duplicated. The
53
+ // kernel bodies (isa_kernel_impl.h) are static, and only the tables below have
54
+ // external linkage. libstdc++'s simd internals are all always_inline, so they
55
+ // leave no mergeable symbols behind either -- verified with nm on both TUs.
56
+ // ---------------------------------------------------------------------------
57
+
58
+ namespace IsoSpec
59
+ {
60
+
61
+ //! Batch-emit configurations of the current marginal-0 run into out_masses/out_probs.
62
+ /*!
63
+ Consumes as much of the run as fills whole vectors, leaving the remaining
64
+ fewer-than-W configurations to the caller's scalar drain. Advances
65
+ *lProbs_ptr past what it consumed and returns how many it emitted.
66
+
67
+ \param lProbs_ptr In/out cursor; on entry it points at the last-emitted
68
+ configuration, per the generators' "advance, then emit"
69
+ convention.
70
+ \param lProbs_start Index 0 of marginal 0's log-probability array.
71
+ \param marginal_masses, marginal_probs Marginal 0's tables, indexed as lProbs is.
72
+ \param lcfmsv The cutoff the run ends at.
73
+ \param partial_mass, partial_prob The higher marginals' contribution, constant
74
+ across the run.
75
+ */
76
+ typedef std::size_t (*isa_fill_run_fn)(const double** lProbs_ptr,
77
+ const double* lProbs_start,
78
+ const double* marginal_masses,
79
+ const double* marginal_probs,
80
+ double lcfmsv,
81
+ double partial_mass,
82
+ double partial_prob,
83
+ double* out_masses,
84
+ double* out_probs);
85
+
86
+ //! As above, but scattering into a dense bin accumulator instead of storing.
87
+ /*! acc must already be rebased so that a bin index of any sign is in range. */
88
+ typedef std::size_t (*isa_bin_run_fn)(const double** lProbs_ptr,
89
+ const double* lProbs_start,
90
+ const double* marginal_masses,
91
+ const double* marginal_probs,
92
+ double lcfmsv,
93
+ double partial_mass,
94
+ double partial_prob,
95
+ double* acc,
96
+ double hwmm,
97
+ double inv_bin_width);
98
+
99
+ //! One instruction-set level's build of the kernels.
100
+ struct IsaKernels {
101
+ isa_fill_run_fn fill_run;
102
+ isa_bin_run_fn bin_run;
103
+ const char* name; /*!< For diagnostics and the tests. */
104
+ std::size_t lanes; /*!< Doubles per vector; 1 when there is no SIMD at all. */
105
+ };
106
+
107
+ //! ISA levels, ordered by capability. Only ever grows at the top.
108
+ /*! The numeric order IS the capability order -- best_available_level() picks the
109
+ highest usable value -- so a new level in the middle renumbers the ones above
110
+ it. That is an ABI break for anything already compiled against this header,
111
+ and is why ISA_LEVEL_AVX was inserted before 2.4.0 shipped rather than after.
112
+ Any level added from now on goes on the top, or the ordering stops being
113
+ expressible as `<`.
114
+
115
+ Note there is deliberately no x86-64-v2 level: v2 is SSE4.2 and POPCNT, which
116
+ do not widen a vector of doubles at all, so it would be identical to the
117
+ baseline in every way that matters here. */
118
+ enum IsaLevel {
119
+ ISA_LEVEL_BASELINE = 0, /*!< Whatever the unadorned target gives: SSE2 on x86-64, NEON on AArch64. */
120
+ ISA_LEVEL_AVX = 1, /*!< AVX without AVX2: 4 doubles, no FMA. Sandy/Ivy Bridge, Bulldozer-Excavator. */
121
+ ISA_LEVEL_V3 = 2, /*!< x86-64-v3: AVX2 + FMA, 4 doubles. */
122
+ ISA_LEVEL_V4 = 3, /*!< x86-64-v4: AVX-512F/BW/DQ/VL, 8 doubles. */
123
+ ISA_LEVEL_COUNT = 4
124
+ };
125
+
126
+ //! The kernels selected for this machine. Resolved once, on first call.
127
+ const IsaKernels& isa_kernels();
128
+
129
+ //! The level those kernels came from.
130
+ IsaLevel current_isa_level();
131
+
132
+ //! Highest level this build contains *and* this CPU supports.
133
+ IsaLevel max_supported_isa_level();
134
+
135
+ //! Is this level present in the binary and usable on this CPU?
136
+ bool isa_level_available(IsaLevel level);
137
+
138
+ //! Force a level, for testing and for working around a bad CPU.
139
+ /*! Returns false and changes nothing if the level is not available. Also
140
+ settable through the ISOSPEC_ISA_LEVEL environment variable
141
+ ("baseline", "v3", "v4"), read when the selection is first resolved. */
142
+ bool set_isa_level(IsaLevel level);
143
+
144
+ const char* isa_level_name(IsaLevel level);
145
+
146
+ //! What the batched kernels actually running on this machine are vectorised to.
147
+ /*!
148
+ A stable lowercase token, never NULL and never to be freed: one of
149
+
150
+ - "scalar" -- no vectorisation at all. Either the standard library has no
151
+ <experimental/simd> (MSVC, and Apple Clang's libc++), or the
152
+ build disabled the SIMD path; every configuration goes
153
+ through the scalar drain and the kernels are do-nothing stubs.
154
+ - "sse2" -- x86-64's guaranteed baseline, 2 doubles per vector.
155
+ - "avx" -- 4 doubles, no FMA (a -march build targeting pre-Haswell x86).
156
+ - "avx2" -- x86-64-v3: AVX2+FMA, 4 doubles.
157
+ - "avx512" -- x86-64-v4: AVX-512F/BW/DQ/VL, 8 doubles.
158
+ - "neon" -- AArch64's guaranteed baseline, 2 doubles.
159
+ - "simd" -- vectorised, on an architecture this function has no name for.
160
+
161
+ This is a finer-grained question than current_isa_level(), and deliberately
162
+ so: that one names the dispatch bucket, which says nothing about whether the
163
+ bucket's kernels vectorise. A build whose standard library lacks the SIMD
164
+ header still reports level "baseline" while running entirely scalar -- the
165
+ case this function exists to make visible.
166
+
167
+ New tokens may be added as levels are; treat an unrecognised one as "some
168
+ vector unit", not as an error.
169
+ */
170
+ const char* active_simd_level();
171
+
172
+ } // namespace IsoSpec
@@ -0,0 +1,121 @@
1
+ /*
2
+ * Copyright (C) 2015-2020 Mateusz Łącki and Michał Startek.
3
+ *
4
+ * This file is part of IsoSpec.
5
+ *
6
+ * IsoSpec is free software: you can redistribute it and/or modify
7
+ * it under the terms of the Simplified ("2-clause") BSD licence.
8
+ *
9
+ * IsoSpec is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
+ *
13
+ * You should have received a copy of the Simplified BSD Licence
14
+ * along with IsoSpec. If not, see <https://opensource.org/licenses/BSD-2-Clause>.
15
+ */
16
+
17
+ #pragma once
18
+
19
+ #include <atomic>
20
+ #include <cmath>
21
+ #include <cstddef>
22
+ #include <cstdint>
23
+ #include <random>
24
+
25
+ #if !defined(ISOSPEC_G_FACT_TABLE_SIZE)
26
+ // 10M should be enough for anyone, right?
27
+ // Actually, yes. If anyone tries to input a molecule that has more than 10M atoms,
28
+ // he deserves to get an exception thrown in his face. OpenMS guys don't want to alloc
29
+ // a table of 10M to memoize the necessary values though, use something smaller for them.
30
+ #if ISOSPEC_BUILDING_OPENMS
31
+ #define ISOSPEC_G_FACT_TABLE_SIZE 1024
32
+ #else
33
+ #define ISOSPEC_G_FACT_TABLE_SIZE 1024*1024*10
34
+ #endif
35
+ #endif
36
+
37
+ // Prefix of g_lfact_table that is filled eagerly at startup. Accessing those
38
+ // entries needs no synchronisation (immutable post-init); the lazy tail above
39
+ // goes through std::atomic_ref to keep the racing fill thread-safe.
40
+ #if !defined(ISOSPEC_LFACT_EAGER_FILL)
41
+ #if ISOSPEC_BUILDING_OPENMS
42
+ #define ISOSPEC_LFACT_EAGER_FILL ISOSPEC_G_FACT_TABLE_SIZE
43
+ #else
44
+ #define ISOSPEC_LFACT_EAGER_FILL 65536
45
+ #endif
46
+ #endif
47
+
48
+ namespace IsoSpec
49
+ {
50
+
51
+ extern double* g_lfact_table;
52
+
53
+ static inline double minuslogFactorial(int n)
54
+ {
55
+ if (n < 2)
56
+ return 0.0;
57
+ if (static_cast<std::size_t>(n) < static_cast<std::size_t>(ISOSPEC_LFACT_EAGER_FILL))
58
+ return g_lfact_table[n]; // immutable after startup
59
+
60
+ #if ISOSPEC_BUILDING_OPENMS
61
+ if (n >= ISOSPEC_G_FACT_TABLE_SIZE)
62
+ return -lgamma(n+1);
63
+ #endif
64
+
65
+ std::atomic_ref<double> slot(g_lfact_table[n]);
66
+ double v = slot.load(std::memory_order_relaxed);
67
+ if (v == 0.0) {
68
+ v = -lgamma(n+1);
69
+ slot.store(v, std::memory_order_relaxed);
70
+ }
71
+ return v;
72
+ }
73
+
74
+ const double pi = 3.14159265358979323846264338328;
75
+ const double logpi = 1.144729885849400174143427351353058711647294812915311571513623071472137769884826079783623270275489708;
76
+
77
+ double NormalCDFInverse(double p);
78
+ double NormalCDFInverse(double p, double mean, double stdev);
79
+ double NormalCDF(double x, double mean, double stdev);
80
+ double NormalPDF(double x, double mean = 0.0, double stdev = 1.0);
81
+
82
+ // Returns lower incomplete gamma function of a/2, x, where a is int and > 0.
83
+ double LowerIncompleteGamma2(int a, double x);
84
+
85
+ // Returns y such that LowerIncompleteGamma2(a, y) == x. Approximately.
86
+ double InverseLowerIncompleteGamma2(int a, double x);
87
+
88
+ // Computes the inverse Cumulative Distribution Funcion of the Chi-Square distribution with k degrees of freedom
89
+ inline double InverseChiSquareCDF2(int k, double x)
90
+ {
91
+ return InverseLowerIncompleteGamma2(k, x*tgamma(static_cast<double>(k)/2.0)) * 2.0;
92
+ }
93
+
94
+ extern thread_local std::mt19937 random_gen;
95
+
96
+ //! Uniform draw from [0,1), 53-bit resolution.
97
+ /*! Not std::uniform_real_distribution: libstdc++ routes that through
98
+ std::generate_canonical, which takes std::log2 of a long double at every
99
+ call -- __ieee754_logl alone was 21% of FromStochastic's runtime profile.
100
+ Two raw 32-bit draws glued into a 53-bit mantissa produce the same
101
+ distribution directly. Measured: 1.51x end-to-end on FromStochastic
102
+ (C23832H37816N6528O7031S170, 3e7 molecules, Piledriver). */
103
+ inline double rdvariate_unif01(std::mt19937& rgen = random_gen)
104
+ {
105
+ uint64_t hi = rgen();
106
+ uint64_t lo = rgen();
107
+ return static_cast<double>(((hi << 32) | lo) >> 11) * 0x1.0p-53;
108
+ }
109
+
110
+ inline double rdvariate_beta_1_b(double b, std::mt19937& rgen = random_gen)
111
+ {
112
+ return 1.0 - pow(rdvariate_unif01(rgen), 1.0/b);
113
+ }
114
+
115
+
116
+ size_t rdvariate_binom(size_t tries, double succ_prob, std::mt19937& rgen = random_gen);
117
+
118
+
119
+
120
+
121
+ } // namespace IsoSpec