uLib  User mode C/C++ extended API library for Win32 programmers.
Common.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Common. Small "ubiquitous" utities, et c.
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 #include <uLib\Common.h>
9 
10 HINSTANCE hInstance = NULL;
11 
12 HWND hMainWnd = NULL;
13 HWND hCurrDlg = NULL;
14 HACCEL hMainAcc = NULL;
15 HWND hMdiClient = NULL;
16 
17 #if !USE_STATIC_SECDESC_INIT
18 
19 PISECURITY_DESCRIPTOR pis;
20 SECURITY_ATTRIBUTES DefSec = { sizeof(DefSec), NULL, TRUE }; // Use default sec.desc. of calling process.
21 SECURITY_DESCRIPTOR DefSecDesc = { 0,0,0,NULL,NULL,NULL,NULL }; // All yours.
22 
23 #else
24 // Setup sec desc with a NULL DACL (gives full Access to Everyone)
25 // (This is what the descriptor would look like after InitializeSecDesc.)
26 
27 SECURITY_DESCRIPTOR DefSecDesc = {
28  SECURITY_DESCRIPTOR_REVISION, 0,
29  SE_DACL_PRESENT, // NULL DACL present
30  (PSID)NULL, // Owner
31  (PSID)NULL, // Group
32  (PACL)NULL, // Sacl
33  (PACL)NULL // Dacl
34  };
35 SECURITY_ATTRIBUTES DefSec = { sizeof(DefSec), &DefSecDesc, TRUE };
36 
37 #endif
38 
39 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40 // Windows version check
41 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42 
45 #if 0 //defined(_MSC_VER) && (_WIN32_WINNT >= telephone_crap)
46 // Agh... The millennial airheads /deprecated/ GetVersion() in the Win10 SDK !!
47 // Well eff that... "See figure 1" (of an (in)famous VMS memo).
48 // Good programmers know how to handle their nibbles!
49 static DWORD _GetVersion(void)
50 {
51  static DWORD (WINAPI *__GetVersion)(void) = NULL;
52  DWORD version = 0;
53  if (!__GetVersion) // We know where you live..
54  {
55  HMODULE hMod = GetModuleHandle( "kernel32" );
56  if (hMod) (FARPROC&)__GetVersion = GetProcAddress( hMod, "GetVersion" );
57  }
58  if (__GetVersion) version = __GetVersion();
59  else // Let's make this bullet proof.
60  {
61  OSVERSIONINFO vi; memset( &vi, 0, sizeof(vi) );
62  vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
63  if (GetVersionEx( &vi ))
64  {
65  version = (vi.dwMajorVersion & 0xFF) | ((vi.dwMinorVersion & 0xFF) << 8)
66  | (vi.dwBuildNumber << 16);
67  if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) version |= 0x80000000;
68  }
69  }
70  return version;
71 }
72 #else
73 #define _GetVersion GetVersion
74 #endif
77 
78 bool IsWinVer( BYTE vMajor, BYTE vMinor, bool winNt )
79 {
80  // Return true if Windows version is *greater or equal* than argument.
81 
82  #define DW_HIGH_BIT 0x80000000L
83  DWORD platform = winNt ? 0 : DW_HIGH_BIT; // High bit zero is NT
84  DWORD version = _GetVersion();
85 
86  bool isOk = ((version & DW_HIGH_BIT) == platform);
87  if (isOk) isOk = (LOBYTE( LOWORD( version )) >= vMajor);
88  if (isOk) isOk = (HIBYTE( LOWORD( version )) >= vMinor);
89  return isOk;
90 }
91 
92 bool IsWin7() { return IsWinVer( 6,1, true ); }
93 bool IsWinVista() { return IsWinVer( 6,0, true ); }
94 bool IsWinXP() { return IsWinVer( 5,1, true ); }
95 bool IsWin2000() { return IsWinVer( 5,0, true ); }
96 bool IsWinNT() { return IsWinVer( 4,0, true ); }
97 bool IsWin98() { return IsWinVer( 4,1, false ); }
98 bool IsWin95() { return IsWinVer( 4,0, false ); }
99 
100 bool IsWin64Bit() // Check if running on Windows x64 version
101 {
102  #if defined(_WIN64)
103  return true; // This is a 64 bit proc, and running (duh), so Windows is x64.
104  #elif defined(_WIN32)
105  return IsWow64(); // If we're running under WoW64, the OS is x64
106  #else
107  #error [uLib/Common] Please define IsWin64Bit for your platform.
108  #endif
109 }
110 
111 bool IsWow64()
112 {
113  #if defined(_WIN64)
114  return false; // This is a 64 bit proc, so we're not on WoW64.
115  #else
116  BOOL isWow64 = FALSE;
117  static BOOL (WINAPI *_IsWow64Process)( HANDLE hProc, PBOOL pWow64Proc );
118  // (IsWow64Process is not available on all versions of Windows.)
119 
120  SetLastError( 0 );
121  if (!_IsWow64Process)
122  {
123  HMODULE hKernel = GetModuleHandle(_T("KERNEL32"));
124  (FARPROC&)_IsWow64Process = GetProcAddress( hKernel, "IsWow64Process" );
125  }
126  if (_IsWow64Process) // If API is available
127  if (!_IsWow64Process( GetCurrentProcess(), &isWow64 ))
128  {
129  isWow64 = FALSE; // API call failed
130  }
131  return bool_cast( isWow64 ); // True if we're running under WoW64
132  #endif
133 }
134 
135 void GetWinSystemInfo( SYSTEM_INFO* si )
136 {
137  if (IsWow64()) GetNativeSystemInfo( si );
138  else GetSystemInfo( si );
139 }
140 
141 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142 // Arithmetic
143 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
144 
145 long map( long x, long xMin, long xMax, long toMin, long toMax )
146 {
147  // Promoting the numerator size solves the intermediate overflow problem
148  return toMin + (INT64( x - xMin ) * INT64( toMax - toMin )) / (xMax - xMin);
149 }
150 
151 long constrain( long x, long lo, long hi )
152 {
153  return (x > hi ? hi : (x < lo ? lo : x));
154 }
155 
156 short random( short iMin, short iMax )
157 {
158  #if 0 // map can be used, but is overkill in ths case.
159  return map( rand(), 0, RAND_MAX, iMin, iMax );
160  #else
161  int range = iMax - iMin; // I want *inclusive* iMin, iMax.
162  return short( iMin + rand() * range / RAND_MAX );
163  //return short( iMin + MulDiv( rand(), range, RAND_MAX ));
164  #endif
165 }
166 
167 void randomize()
168 {
169  LARGE_INTEGER li;
170  QueryPerformanceCounter( &li );
171  srand( li.LowPart );
172 }
173 
174 // Return the new running Avg..
175 
176 long runningAvg( long Avg, long X, unsigned int Period )
177 {
178  return (X + ((Period-1)*Avg)) / Period;
179 }
180 
181 // Integer power of 2, by left shift.
182 
184 {
185  //X &= 0x1F; // Enforce max 31 bit shift
186  return (1L << X);
187 }
188 
190 {
191  //X &= 0x3F; // Enforce max 63 bit shift
192  return (1ULL << X);
193 }
194 
195 // Integer log2 of x, by right shift.
196 
197 #if 0 // Original loop, gets slowish for large X.
198 ushort ilog2( ulong X )
199 {
200  ushort y = 0;
201  while( X >>= 1 ) y++; // Naive brute force loop..
202  return y;
203 }
204 #else // This algorithm is up to 3.7 times faster for large X :)
205 
206 // [REF] http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
207 
209 {
210  #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
211  #pragma pack( push, 1 )
212  static const int8 Logs[256] =
213  {
214  #if 1 // Standard norm -- ilog2(0) == -1.
215  -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
216  #else // As old one -- Non-standard -- ilog(0) == 0.
217  0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
218  #endif
219  LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
220  LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
221  };
222  #pragma pack( pop )
223  #undef LT
224  register ulong tmp, t2;
225  ushort ilog;
226 
227  // Operationally monotonic - Always 2 shifts.
228 
229  if (tmp = X >> 16)
230  {
231  ilog = (t2 = tmp >> 8) ? 24 + Logs[ t2 ] : 16 + Logs[ tmp ];
232  }
233  else
234  {
235  ilog = (t2 = X >> 8) ? 8 + Logs[ t2 ] : Logs[ X ];
236  }
237  return ilog;
238 }
239 #endif
240 
242 {
243  ulong temp = ulong( X >> 32 );
244  return temp ? 32 + ilog2( temp ) : ilog2( (ulong)X );
245 }
246 
247 ushort ilog10( ulong X ) //Find integer log base 10 of an integer
248 {
249  ushort ilog;
250 
251  // The integer log base 10 is computed by first using one of the techniques above
252  // for finding the log base 2. By the relationship log10(v) = log2(v) / log2(10),
253  // we need to multiply it by 1/log2(10), which is approximately 1233/4096, or 1233
254  // followed by a right shift of 12. Adding one is needed because the ilog2 rounds down.
255  // Finally, since the value t is only an approximation that may be off by one, the
256  // exact value is found by subtracting the result of X < PowersOf10[est].
257 
258  static ulong const Pwr10[] =
259  {
260  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
261  };
262 
263  // PONDER: Find a higher rational for 1/log2(10)..?
264 
265  ulong est = ((ulong(ilog2( X )) + 1) * 1233) >> 12;
266  _ASSERTE( est < dimof(Pwr10) );
267  ilog = ushort( est - (X < Pwr10[ est ]) );
268  return ilog;
269 }
270 
271 ushort ilog10x( uint64 X ) //Find integer log base 10 of an integer
272 {
273  ushort ilog;
274 
275  // See ilog10( ulong X )
276 
277  static uint64 const Pwr10[] =
278  {
279  1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
280  10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000,
281  1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000,
282  10000000000000000000ul
283  };
284 
285  // PONDER: Find a higher rational for 1/log2(10)..?
286 
287  ulong est = (ulong(ilog2x( X )) + 1) * 1233 >> 12;
288  _ASSERTE( est < dimof(Pwr10) );
289  ilog = ushort( est - (X < Pwr10[ est ]) );
290  return ilog;
291 }
292 
293 // Nth root of x, e.g root( 2,x ) == sqrt( x ).
294 // Uses the inverse power method, nVx <=> x^(1/n)
295 
296 long double _root( long double base, long double x )
297 {
298  return powl( x, (long double)1.0L / base );
299 }
300 
301 // Base n logartithm of x.
302 
303 long double _log( long double base, long double x )
304 {
305  return logl( x ) / logl( base );
306 }
307 
308 // Round a floating point number to arbitrary precision (<= 14).
309 // Alphatest: double x = M_PI;
310 // for( int nd=0; nd < 15; ++nd )
311 // {
312 // double y = _round( x, nd );
313 // printf( "_round( %.15f, %i ) = %.*f\n", x, nd, nd+1, y );
314 // }
315 
316 #if 0 // Use pow() -- expensive.
317 #define _HIGH_PRECISION 0 // Didn't alleviate LSB error :(
318 double _round( double x, unsigned char ndecimals )
319 {
320  if (x != 0.0)
321  {
322  #if _HIGH_PRECISION
323  unsigned int _pc = _control87( 0,0 ) & _MCW_PC; // 53 bit mantissa :(
324  _control87( _PC_64, _MCW_PC ); // 64 bit mantissa - No cure :(
325  #endif
326  #if 0
327  if (ndecimals > 15) ndecimals = 15; // Theoretic limit (<= 2^53 [mantissa])
328  if (ndecimals > 13) ndecimals = 13; // Empiric limit
329  #endif
330 
331  static const double _half = 0.5L;
332  double k = pow( 10.0, ndecimals );
333  x = (double) ceil( x * k - _half) / k; // LSB aberration :(
334 
335  #if _HIGH_PRECISION
336  _control87( _pc, _MCW_PC );
337  #endif
338  }
339  return x;
340 }
341 #undef _HIGH_PRECISION
342 #else
343 double _round( double x, unsigned char ndeci )
344 {
345  static const double _half = 0.5L;
346  // Eliminate expensive pow() calculation with a 120 B lookup table.
347  static const double _pwr[] = { // pow( 10, ndecimals )
348  10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, // 7
349  100000000.0, 1000000000.0, 10000000000.0, 100000000000.0, // 11
350  1000000000000.0, 10000000000000.0, 100000000000000.0 // 14
351  };
352  if (x != 0.0)
353  {
354  //if (!ndeci) x = ceil( x - _half); // Zero decimals (round mathic'ly)
355  if (!ndeci) x = (int) x; // Zero decimals (truncate)
356  else
357  {
358  if (ndeci > dimof(_pwr)) ndeci = dimof(_pwr);
359  double k = _pwr[ ndeci-1 ];
360  x = ceil( x * k - _half) / k;
361  }
362  }
363  return x;
364 }
365 #endif
366 
372 
373 bool _isprime( unsigned long x )
374 {
375  // PONDER: Rewrite this to have a single return point ?
376  if (x < 2) return false;
377  if ((x % 2) == 0) return (x == 2);
378  if ((x % 3) == 0) return (x == 3);
379  if ((x % 5) == 0) return (x == 5);
380 
381  unsigned long n, limit = (unsigned long) sqrt( double( x ));
382  for( n = 7; n <= limit; n++ )
383  if ((x % n) == 0)
384  return false; // Divisible by 7..sqrt(x).
385 
386  return true; // Prime.. Passed the exclusion loop.
387 }
388 
389 // FYI, The following two where originally implemented to select
390 // delay line lengths for DSP reverb algorithms. Primes matter!
391 
393 
394 unsigned long _prime( unsigned long x )
395 {
396  unsigned long i = 0;
397  if (_isprime( x )) return x;
398  while( ++i ) if (_isprime( x+i )) return x+i;
399  return 0;
400 }
401 
403 
404 unsigned long _nearprime( unsigned long x )
405 {
406  unsigned long i = 0;
407  if (_isprime( x )) return x;
408  while( ++i )
409  {
410  unsigned long j = x + i;
411  if (_isprime( j )) return j;
412  else {
413  j = x - i;
414  if ((j > 2) && _isprime( j )) return j;
415  }
416  }
417  return 0;
418 }
419 
420 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
421 // Fallback C implementations for byte swapping.
422 // NOT preferred. However, the ASM code is currently only for ML/ML64.
423 // Lucky enough, there are intrinsic bswaps in most cases.
424 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
425 
426 #if !HAVE_BSWAP16_INTRINSIC
427  #if !HAVE_ASM_BSWAP
428  UINT16 __cdecl _bswap16( UINT16 W )
429  {
430  // C fallback if no assembler available.
431  return (W << 8) | (W >> 8);
432  }
433  #endif
434 #endif
435 
436 #if !HAVE_BSWAP32_INTRINSIC
437  #if !HAVE_ASM_BSWAP
438  UINT32 __cdecl _bswap32( UINT32 DW )
439  {
440  // C fallback if no assembler available.
441  return (DW << 24) | (DW >> 24)
442  | ((DW & 0x00FF0000) >> 8) | ((DW & 0x0000FF00) << 8);
443  }
444  #endif
445 #endif
446 
447 #if !HAVE_BSWAP64_INTRINSIC
448  #if !HAVE_ASM_BSWAP
449  UINT64 __cdecl _bswap64( UINT64 Val )
450  {
451  // C fallback if no assembler available.
452  union uSwap {
453  UINT64 u64;
454  BYTE b[8];
455  } u;
456 
457  u.u64 = Val;
458  for( BYTE i=0, j=7; i < 4; ++i, --j )
459  {
460  BYTE _b = u.b[i]; u.b[i] = u.b[j]; u.b[j] = _b;
461  }
462  return u.u64;
463  }
464  #endif
465 #endif
466 
467 // EOF
ushort ilog2(ulong X)
Definition: Common.cpp:208
unsigned long DWORD
Definition: Common.h:414
signed char int8
Definition: uLib/Types.h:66
short random(short iMin, short iMax)
Definition: Common.cpp:156
UINT64 __cdecl _bswap64(UINT64 Val)
Definition: Common.cpp:449
bool IsWin7()
Definition: Common.cpp:92
long double _log(long double base, long double x)
Definition: Common.cpp:303
bool IsWin98()
Definition: Common.cpp:97
#define BEGIN_ANONYMOUS
Definition: Common.h:226
bool IsWinVista()
Definition: Common.cpp:93
HWND hCurrDlg
Definition: Common.cpp:13
#define DW_HIGH_BIT
ushort ilog2x(uint64 X)
Definition: Common.cpp:241
UINT16 __cdecl _bswap16(UINT16 W)
Definition: Common.cpp:428
#define dimof(x)
Definition: Common.h:949
ulong ipow2(ushort X)
Definition: Common.cpp:183
unsigned long _prime(unsigned long x)
Return nearest prime number not smaller than x.
Definition: Common.cpp:394
uint64 ipow2x(ushort X)
Definition: Common.cpp:189
unsigned __int64 uint64
Definition: uLib/Types.h:51
ushort ilog10x(uint64 X)
Definition: Common.cpp:271
bool IsWinNT()
Definition: Common.cpp:96
UINT32 __cdecl _bswap32(UINT32 DW)
Definition: Common.cpp:438
bool IsWinVer(BYTE vMajor, BYTE vMinor, bool winNt)
Definition: Common.cpp:78
void randomize()
Definition: Common.cpp:167
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
bool _isprime(unsigned long x)
Definition: Common.cpp:373
void GetWinSystemInfo(SYSTEM_INFO *si)
Definition: Common.cpp:135
PISECURITY_DESCRIPTOR pis
Definition: Common.cpp:19
HACCEL hMainAcc
Definition: Common.cpp:14
SECURITY_DESCRIPTOR DefSecDesc
Definition: Common.cpp:21
bool IsWin95()
Definition: Common.cpp:98
bool IsWinXP()
Definition: Common.cpp:94
signed __int64 INT64
Definition: Common.h:401
long constrain(long x, long lo, long hi)
Definition: Common.cpp:151
unsigned __int64 UINT64
Definition: Common.h:400
bool IsWin2000()
Definition: Common.cpp:95
unsigned short ushort
Definition: uLib/Types.h:46
long runningAvg(long Avg, long X, unsigned int Period)
Definition: Common.cpp:176
SECURITY_ATTRIBUTES DefSec
Definition: Common.cpp:20
unsigned long ulong
Definition: uLib/Types.h:47
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
double _round(double x, unsigned char ndeci)
Definition: Common.cpp:343
HWND hMdiClient
Definition: Common.cpp:15
long map(long x, long xMin, long xMax, long toMin, long toMax)
Definition: Common.cpp:145
long double _root(long double base, long double x)
Definition: Common.cpp:296
ushort ilog10(ulong X)
Definition: Common.cpp:247
HINSTANCE hInstance
Definition: Common.cpp:10
Common include; Added types, small "ubiquitous" utilities, et c.
unsigned long _nearprime(unsigned long x)
Return nearest prime above or below x, or precisely x.
Definition: Common.cpp:404
#define END_ANONYMOUS
Definition: Common.h:227
bool IsWow64()
Definition: Common.cpp:111
HWND hMainWnd
Definition: Common.cpp:12
#define LT(n)
bool IsWin64Bit()
Definition: Common.cpp:100
unsigned char BYTE
Definition: Common.h:412