Tissue Forge C++ 0.2.1
Interactive, particle-based physics, chemistry and biology modeling and simulation environment
Loading...
Searching...
No Matches
tf_util.h
Go to the documentation of this file.
1/*******************************************************************************
2 * This file is part of Tissue Forge.
3 * Copyright (c) 2022-2024 T.J. Sego
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 ******************************************************************************/
19
25#ifndef _SOURCE_TF_UTIL_H_
26#define _SOURCE_TF_UTIL_H_
27
28#include "TissueForge_private.h"
29
30#include <Magnum/Magnum.h>
31#include <Magnum/Math/Color.h>
32#include <bitset>
33#include <tf_cycle.h>
34#include <string>
35#include <list>
36#include <unordered_map>
37#include <unordered_set>
38#include <random>
39
40#ifdef _WIN32
41#define _USE_MATH_DEFINES
42#endif
43#include <cmath>
44#include <limits>
45#include <type_traits>
46
47
48namespace TissueForge {
49
50
51 typedef std::mt19937 RandomType;
52 RandomType &randomEngine();
53
58 CPPAPI_FUNC(unsigned int) getSeed();
59
66 CPPAPI_FUNC(HRESULT) setSeed(const unsigned int *_seed=0);
67
68 enum class PointsType : unsigned int {
69 Sphere,
70 SolidSphere,
71 Disk,
72 SolidCube,
73 Cube,
74 Ring
75 };
76
82 CPPAPI_FUNC(std::vector<std::string>) color3Names();
83
91 CPPAPI_FUNC(FVector4) planeEquation(const FVector3 &normal, const FVector3 &point);
92
99 CPPAPI_FUNC(std::tuple<FVector3, FVector3>) planeEquation(const FVector4 &planeEq);
100
112 CPPAPI_FUNC(FVector3) randomPoint(
113 const PointsType &kind,
114 const FloatP_t &dr=0,
115 const FloatP_t &phi0=0,
116 const FloatP_t &phi1=M_PI
117 );
118
131 CPPAPI_FUNC(std::vector<FVector3>) randomPoints(
132 const PointsType &kind,
133 const int &n=1,
134 const FloatP_t &dr=0,
135 const FloatP_t &phi0=0,
136 const FloatP_t &phi1=M_PI
137 );
138
148 CPPAPI_FUNC(std::vector<FVector3>) points(const PointsType &kind, const unsigned int &n=1);
149
160 CPPAPI_FUNC(std::vector<FVector3>) filledCubeUniform(
161 const FVector3 &corner1,
162 const FVector3 &corner2,
163 const unsigned int &nParticlesX=2,
164 const unsigned int &nParticlesY=2,
165 const unsigned int &nParticlesZ=2
166 );
167
176 CPPAPI_FUNC(std::vector<FVector3>) filledCubeRandom(const FVector3 &corner1, const FVector3 &corner2, const int &nParticles);
177
188 CPPAPI_FUNC(HRESULT) icosphere(
189 const int subdivisions,
190 FloatP_t phi0,
191 FloatP_t phi1,
192 std::vector<FVector3> &verts,
193 std::vector<int32_t> &inds
194 );
195
205 CPPAPI_FUNC(FVector3) randomVector(FloatP_t mean, FloatP_t std);
206
213
214 template<class T>
215 typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
216 almost_equal(T x, T y, int ulp = 2)
217 {
218 // the machine epsilon has to be scaled to the magnitude of the values used
219 // and multiplied by the desired precision in ULPs (units in the last place)
220 return std::fabs(x-y) <= std::numeric_limits<T>::epsilon() * std::fabs(x+y) * ulp
221 // unless the result is subnormal
222 || std::fabs(x-y) < std::numeric_limits<T>::min();
223 }
224
225 #ifdef _WIN32
226 // windows
227 inline void* aligned_Malloc(size_t size, size_t alignment) {
228 return _aligned_malloc(size, alignment);
229 }
230
231 inline void aligned_Free(void *mem) {
232 return _aligned_free(mem);
233 }
234
235 #elif __APPLE__
236 // mac
237 inline void* aligned_Malloc(size_t size, size_t alignment)
238 {
239 enum {
240 void_size = sizeof(void*)
241 };
242 if (!size) {
243 return 0;
244 }
245 if (alignment < void_size) {
246 alignment = void_size;
247 }
248 void* p;
249 if (::posix_memalign(&p, alignment, size) != 0) {
250 p = 0;
251 }
252 return p;
253 }
254
255 inline void aligned_Free(void *mem) {
256 return free(mem);
257 }
258
259 #else
260 // linux
261 inline void* aligned_Malloc(size_t size, size_t alignment) {
262 return aligned_alloc(alignment, size);
263 }
264
265 inline void aligned_Free(void *mem) {
266 return free(mem);
267 }
268
269 #endif
270
271
272 namespace util {
273
274
275 extern const char* color3_Names[];
276
277 Magnum::Color3 Color3_Parse(const std::string &str);
278
290 template<typename XType, typename DivType> XType mod(XType x, DivType divisor)
291 {
292 return (divisor + (x%divisor)) % divisor;
293 }
294
295 //Returns floor(a/n) (with the division done exactly).
296 //Let ÷ be mathematical division, and / be C++ division.
297 //We know
298 // a÷b = a/b + f (f is the remainder, not all
299 // divisions have exact Integral results)
300 //and
301 // (a/b)*b + a%b == a (from the standard).
302 //Together, these imply (through algebraic manipulation):
303 // sign(f) == sign(a%b)*sign(b)
304 //We want the remainder (f) to always be >=0 (by definition of flooredDivision),
305 //so when sign(f) < 0, we subtract 1 from a/n to make f > 0.
306 template<typename TA, typename TN>
307 TA flooredDivision(TA a, TN n) {
308 TA q(a/n);
309 if ((a%n < 0 && n > 0) || (a%n > 0 && n < 0)) --q;
310 return q;
311 }
312
313 //flooredModulo: Modulo function for use in the construction
314 //looping topologies. The result will always be between 0 and the
315 //denominator, and will loop in a natural fashion (rather than swapping
316 //the looping direction over the zero point (as in C++11),
317 //or being unspecified (as in earlier C++)).
318 //Returns x such that:
319 //
320 //Real a = Real(numerator)
321 //Real n = Real(denominator)
322 //Real r = a - n*floor(n/d)
323 //x = Integral(r)
324 template<typename TA, typename TN>
325 TA flooredModulo(TA a, TN n) {
326 return a - n * flooredDivision(a, n);
327 }
328
329 template<typename TA, typename TN>
330 TA loopIndex(TA index, TN range) {
331 return mod(index + range, range);
332 }
333
338 template<typename Vec, typename Val>
339 int indexOf(const Vec& vec, const Val& val) {
340 int result = std::find(vec.begin(), vec.end(), val) - vec.begin();
341 return result < vec.size() ? result : -1;
342 }
343
344 template<typename ContainerType, typename SizeType>
345 typename ContainerType::value_type wrappedAt(ContainerType &container, SizeType index) {
346 SizeType wrappedIndex = loopIndex(index, container.size());
347 return container.at(wrappedIndex);
348 }
349
350 template <typename Type, typename Klass>
351 inline constexpr size_t offset_of(Type Klass::*member) {
352 constexpr Klass object {};
353 return size_t(&(object.*member)) - size_t(&object);
354 }
355
356 enum InstructionSetFlags : std::int64_t {
357 IS_3DNOW = 1ll << 0,
358 IS_3DNOWEXT = 1ll << 1,
359 IS_ABM = 1ll << 2,
360 IS_ADX = 1ll << 3,
361 IS_AES = 1ll << 4,
362 IS_AVX = 1ll << 5,
363 IS_AVX2 = 1ll << 6,
364 IS_AVX512CD = 1ll << 7,
365 IS_AVX512ER = 1ll << 8,
366 IS_AVX512F = 1ll << 9,
367 IS_AVX512PF = 1ll << 10,
368 IS_BMI1 = 1ll << 11,
369 IS_BMI2 = 1ll << 12,
370 IS_CLFSH = 1ll << 13,
371 IS_CMPXCHG16B = 1ll << 14,
372 IS_CX8 = 1ll << 15,
373 IS_ERMS = 1ll << 16,
374 IS_F16C = 1ll << 17,
375 IS_FMA = 1ll << 18,
376 IS_FSGSBASE = 1ll << 19,
377 IS_FXSR = 1ll << 20,
378 IS_HLE = 1ll << 21,
379 IS_INVPCID = 1ll << 23,
380 IS_LAHF = 1ll << 24,
381 IS_LZCNT = 1ll << 25,
382 IS_MMX = 1ll << 26,
383 IS_MMXEXT = 1ll << 27,
384 IS_MONITOR = 1ll << 28,
385 IS_MOVBE = 1ll << 28,
386 IS_MSR = 1ll << 29,
387 IS_OSXSAVE = 1ll << 30,
388 IS_PCLMULQDQ = 1ll << 31,
389 IS_POPCNT = 1ll << 32,
390 IS_PREFETCHWT1 = 1ll << 33,
391 IS_RDRAND = 1ll << 34,
392 IS_RDSEED = 1ll << 35,
393 IS_RDTSCP = 1ll << 36,
394 IS_RTM = 1ll << 37,
395 IS_SEP = 1ll << 38,
396 IS_SHA = 1ll << 39,
397 IS_SSE = 1ll << 40,
398 IS_SSE2 = 1ll << 41,
399 IS_SSE3 = 1ll << 42,
400 IS_SSE41 = 1ll << 43,
401 IS_SSE42 = 1ll << 44,
402 IS_SSE4a = 1ll << 45,
403 IS_SSSE3 = 1ll << 46,
404 IS_SYSCALL = 1ll << 47,
405 IS_TBM = 1ll << 48,
406 IS_XOP = 1ll << 49,
407 IS_XSAVE = 1ll << 50,
408 };
409
410 #if defined(__x86_64__) || defined(_M_X64)
411
412 // Yes, Windows has the __cpuid and __cpuidx macros in the #include <intrin.h>
413 // header file, but it seg-faults when we try to call them from clang.
414 // this version of the cpuid seems to work with clang on both Windows and mac.
415
416 // adapted from https://github.com/01org/linux-sgx/blob/master/common/inc/internal/linux/cpuid_gnu.h
417 /* This is a PIC-compliant version of CPUID */
418 static inline void __tf_cpuid(int *eax, int *ebx, int *ecx, int *edx)
419 {
420 #if defined(__x86_64__)
421 asm("cpuid"
422 : "=a" (*eax),
423 "=b" (*ebx),
424 "=c" (*ecx),
425 "=d" (*edx)
426 : "0" (*eax), "2" (*ecx));
427
428 #else
429 int regs[] = {*eax, *ebx, *ecx, *edx};
430 __cpuid(regs, *eax);
431 *eax = regs[0];
432 *ebx = regs[1];
433 *ecx = regs[2];
434 *edx = regs[3];
435 #endif
436 }
437
438 #ifdef _WIN32
439
440 // TODO: PATHETIC HACK for windows.
441 // don't know why, but calling cpuid in release mode, and ONLY in release
442 // mode causes a segfault. Hack is to flush stdout, push some junk on the stack.
443 // and force a task switch.
444 // dont know why this works, but if any of these are not here, then it segfaults
445 // in release mode.
446 // this also seems to work, but force it non-inline and return random
447 // number.
448 // Maybe the optimizer is inlining it, and inlining causes issues
449 // calling cpuid???
450
451 static __declspec(noinline) int tf_cpuid(int a[4], int b)
452 {
453 a[0] = b;
454 a[2] = 0;
455 __tf_cpuid(&a[0], &a[1], &a[2], &a[3]);
456 return std::rand();
457 }
458
459 static __declspec(noinline) int tf_cpuidex(int a[4], int b, int c)
460 {
461 a[0] = b;
462 a[2] = c;
463 __tf_cpuid(&a[0], &a[1], &a[2], &a[3]);
464 return std::rand();
465 }
466
467 #else
468
469 static void tf_cpuid(int a[4], int b)
470 {
471 a[0] = b;
472 a[2] = 0;
473 __tf_cpuid(&a[0], &a[1], &a[2], &a[3]);
474 }
475
476 static void tf_cpuidex(int a[4], int b, int c)
477 {
478 a[0] = b;
479 a[2] = c;
480 __tf_cpuid(&a[0], &a[1], &a[2], &a[3]);
481 }
482
483 #endif
484
485 class CAPI_EXPORT InstructionSet
486 {
487
488 private:
489
490 typedef iVector4 VectorType;
491
492 class InstructionSet_Internal
493 {
494 public:
495 InstructionSet_Internal();
496
497 int nIds_;
498 int nExIds_;
499 std::string vendor_;
500 std::string brand_;
501 bool isIntel_;
502 bool isAMD_;
503 std::bitset<32> f_1_ECX_;
504 std::bitset<32> f_1_EDX_;
505 std::bitset<32> f_7_EBX_;
506 std::bitset<32> f_7_ECX_;
507 std::bitset<32> f_81_ECX_;
508 std::bitset<32> f_81_EDX_;
509 std::vector<VectorType> data_;
510 std::vector<VectorType> extdata_;
511 };
512
513 InstructionSet_Internal CPU_Rep;
514
515
516 public:
517 // getters
518 std::string Vendor(void);
519 std::string Brand(void);
520
521 inline bool SSE3(void);
522 inline bool PCLMULQDQ(void);
523 inline bool MONITOR(void);
524 inline bool SSSE3(void);
525 inline bool FMA(void);
526 inline bool CMPXCHG16B(void);
527 inline bool SSE41(void);
528 inline bool SSE42(void);
529 inline bool MOVBE(void);
530 inline bool POPCNT(void);
531 inline bool AES(void);
532 inline bool XSAVE(void);
533 inline bool OSXSAVE(void);
534 inline bool AVX(void);
535 inline bool F16C(void);
536 inline bool RDRAND(void);
537 inline bool MSR(void);
538 inline bool CX8(void);
539 inline bool SEP(void);
540 inline bool CMOV(void);
541 inline bool CLFSH(void);
542 inline bool MMX(void);
543 inline bool FXSR(void);
544 inline bool SSE(void);
545 inline bool SSE2(void);
546 inline bool FSGSBASE(void);
547 inline bool BMI1(void);
548 inline bool HLE(void);
549 inline bool AVX2(void);
550 inline bool BMI2(void);
551 inline bool ERMS(void);
552 inline bool INVPCID(void);
553 inline bool RTM(void);
554 inline bool AVX512F(void);
555 inline bool RDSEED(void);
556 inline bool ADX(void);
557 inline bool AVX512PF(void);
558 inline bool AVX512ER(void);
559 inline bool AVX512CD(void);
560 inline bool SHA(void);
561 inline bool PREFETCHWT1(void);
562 inline bool LAHF(void);
563 inline bool LZCNT(void);
564 inline bool ABM(void);
565 inline bool SSE4a(void);
566 inline bool XOP(void);
567 inline bool TBM(void);
568 inline bool SYSCALL(void);
569 inline bool MMXEXT(void);
570 inline bool RDTSCP(void);
571 inline bool _3DNOWEXT(void);
572 inline bool _3DNOW(void);
573
574 std::unordered_map<std::string, bool> featuresMap;
575
576 InstructionSet();
577 };
578
579 CPPAPI_FUNC(std::unordered_map<std::string, bool>) getFeaturesMap();
580
581 #else // #if defined(__x86_64__) || defined(_M_X64)
582
583 CPPAPI_FUNC(std::unordered_map<std::string, bool>) getFeaturesMap();
584
585 #endif // #if defined(__x86_64__) || defined(_M_X64)
586
587 class CAPI_EXPORT CompileFlags {
588
589 std::unordered_map<std::string, unsigned int> flags;
590 std::list<std::string> flagNames;
591
592 public:
593
594 CompileFlags();
595 ~CompileFlags() {};
596
597 const std::list<std::string> getFlags();
598 const int getFlag(const std::string &_flag);
599
600 };
601
602
603 CPPAPI_FUNC(double) wallTime();
604
605 CPPAPI_FUNC(double) CPUTime();
606
607
608 class WallTime {
609 public:
610 WallTime();
611 ~WallTime();
612 double start;
613 };
614
616 public:
617 PerformanceTimer(unsigned id);
619 ticks _start;
620 unsigned _id;
621 };
622
623 CPPAPI_FUNC(uint64_t) nextPrime(const uint64_t &start_prime);
624
632 CPPAPI_FUNC(std::vector<uint64_t>) findPrimes(const uint64_t &start_prime, int n);
633
634
636 FloatP_t (*func)(FloatP_t);
637 FloatP_t xmin, xmax, inc_cf = 1e-3;
638
639 Differentiator(FloatP_t (*f)(FloatP_t), const FloatP_t &xmin, const FloatP_t &xmax, const FloatP_t &inc_cf=1e-3);
640
641 FloatP_t fnp(const FloatP_t &x, const unsigned int &order=0);
642 FloatP_t operator() (const FloatP_t &x);
643 };
644
645
653 template <typename T>
654 std::vector<T> unique(const std::vector<T> &vec) {
655 std::unordered_set<T> result_us(vec.begin(), vec.end());
656 return std::vector<T>(result_us.begin(), result_us.end());
657 }
658
659}};
660
661#endif // _SOURCE_TF_UTIL_H_
Definition tfVector4.h:33
Definition tf_util.h:587
Definition tf_util.h:615
Definition tf_util.h:608
std::vector< T > unique(const std::vector< T > &vec)
Get the unique elements of a vector.
Definition tf_util.h:654
std::vector< uint64_t > findPrimes(const uint64_t &start_prime, int n)
Get prime numbers, beginning with a starting prime number.
XType mod(XType x, DivType divisor)
Definition tf_util.h:290
int indexOf(const Vec &vec, const Val &val)
Definition tf_util.h:339
Include Python header, disable linking to pythonX_d.lib on Windows in debug mode.
Definition tfAngleConfig.h:26
FVector3 randomVector(FloatP_t mean, FloatP_t std)
Generates a randomly oriented vector with random magnitude with given mean and standard deviation acc...
std::vector< FVector3 > points(const PointsType &kind, const unsigned int &n=1)
Get the coordinates of uniform points in a kind of shape.
std::vector< FVector3 > filledCubeRandom(const FVector3 &corner1, const FVector3 &corner2, const int &nParticles)
Get the coordinates of a randomly filled cube.
FVector4 planeEquation(const FVector3 &normal, const FVector3 &point)
Get the coefficients of a plane equation for a normal vector and point.
HRESULT icosphere(const int subdivisions, FloatP_t phi0, FloatP_t phi1, std::vector< FVector3 > &verts, std::vector< int32_t > &inds)
Get the coordinates of an icosphere.
std::vector< FVector3 > randomPoints(const PointsType &kind, const int &n=1, const FloatP_t &dr=0, const FloatP_t &phi0=0, const FloatP_t &phi1=M_PI)
Get the coordinates of random points in a kind of shape.
std::vector< FVector3 > filledCubeUniform(const FVector3 &corner1, const FVector3 &corner2, const unsigned int &nParticlesX=2, const unsigned int &nParticlesY=2, const unsigned int &nParticlesZ=2)
Get the coordinates of a uniformly filled cube.
std::vector< std::string > color3Names()
Get the names of all available colors.
HRESULT setSeed(const unsigned int *_seed=0)
Set the current seed for the pseudo-random number generator.
FVector3 randomUnitVector()
Generates a randomly oriented unit vector.
unsigned int getSeed()
Get the current seed for the pseudo-random number generator.
FVector3 randomPoint(const PointsType &kind, const FloatP_t &dr=0, const FloatP_t &phi0=0, const FloatP_t &phi1=M_PI)
Get the coordinates of a random point in a kind of shape.
Definition tf_util.h:635
int32_t HRESULT
Definition tf_port.h:255