What does the code comment 'HD, Figure' mean in Java java.lang.Integer class? - jvm

for example, the JDK method java.lang.Integer.numberOfLeadingZeros(int):
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
what does the code comment 'HD, Figure 5-6' mean?

HD = Hacker's Delight. See the the javadoc:
Implementation note: The implementations of the "bit twiddling" methods (such as highestOneBit and numberOfTrailingZeros) are based on material from Henry S. Warren, Jr.'s Hacker's Delight, (Addison Wesley, 2002).

There are also such comments in java.lang.Long and java.lang.Math.
For example, the addExactmethod in java.lang.Math:
public static int addExact(int x, int y) {
int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
For information of Hacker's Delight we can also refer to: http://hackersdelight.org/

Related

Exception thrown at 0x7A12FF80 (ucrtbased.dll) in Project 3.exe: 0xC0000005: Access violation reading location 0x00000000

I have attempted to run this code. Prior to running this, no warnings or errors exist but once it is executed I have an exception thrown and it stops the program from compiling. Here is my code and the error is in the subject line. The CDA file is being used as header file to create a Circular Dynamic Array that is going to be manipulated in Heaps.cpp. The heaps.cpp is to create a binary heap that is to be used in to create Binomial heaps, but that code has not been developed yet.
#include <iostream>
using namespace std;
template <class T>
class CDA
{
private:
int rear;
int size;
int capacity;
T* circArray;
int front;
bool ordered;
T placeHolder;
public:
CDA();
CDA(int s);
~CDA();
int Front();
T Data(int n);
T& operator[](int i);
void AddEnd(T v);
void AddFront(T v);
void DelEnd();
void DelFront();
int Length();
int Capacity();
int Clear();
bool Ordered();
int SetOrdered();
int S01(int n);
T Select(int k);
void InsertionSort();
void QuickSort();
void QuickSort1(int low, int high);
void CountingSort(int m);
int Search(T e);
void reSize();
void Shrink();
int BinarySearch(int left, int right, T e);
int QSortPartition(int low, int high);
void Swap(int* x, int* y);
int QSelPartition(int front, int rear);
T QuickSelect(int front, int rear, int k);
CDA<T>& operator=(const CDA& a);
CDA(const CDA& old);
int Median(int low, int high);
};
template <class T>
CDA<T>::CDA()
{
capacity = 1;
circArray = new T[capacity];
size = 0;
rear = size - 1;
front = -1;
ordered = false;
placeHolder = 0;
}
template <class T>
CDA<T>::CDA(int s)
{
size = s;
capacity = s;
circArray = new T[capacity];
front = 0;
rear = size - 1;
ordered = false;
}
template <class T>
CDA<T>::CDA(const CDA& a)
{
size = a.size;
capacity = a.capacity;
circArray = new T[a.capacity];
front = a.front;
rear = a.size - 1;
ordered = a.ordered;
for (int i = a.front; i < a.front + (a.size); i++)
{
circArray[i % capacity] = a.circArray[i % capacity];
}
}
template <class T>
CDA<T>::~CDA()
{
delete[]circArray;
}
template <class T>
T& CDA<T>::operator[](int i)
{
if (i > capacity)
{
cout << "Array index is out of bounds; exiting." << endl;
placeHolder = i;
cout << endl;
return placeHolder;
exit(0);
}
else
{
return circArray[(front + i) % capacity];
}
}
template <class T>
void CDA<T>::AddEnd(T v)
{
size++;
if (front == -1)
{
circArray[0] = v;
front++;
rear++;
return;
}
if (size > capacity)
{
reSize();
}
else if (front == -1)
{
front = 0;
rear = size - 1;
}
else
{
rear = (rear + 1) % capacity;
}
circArray[rear] = v;
}
template <class T>
void CDA<T>::AddFront(T v)
{
size++;
if (size > capacity)
{
reSize();
}
if (front == -1) //means the array is empty
{
front = 0;
rear = capacity % size;
}
else if (front == 0) //means something is in spot 0
{
front = capacity - 1; //puts front at the end and places the input there
}
else //go until it is back at zero
{
front--;
}
circArray[front] = v;
}
template <class T>
void CDA<T>::DelEnd()
{
size--;
if (size <= capacity / 4)
{
Shrink();
}
else if (rear == front)
{
front = -1;
rear = -1;
}
else
{
rear--;
}
}
template <class T>
void CDA<T>::DelFront()
{
size--;
double shrMeasure;
shrMeasure = capacity / 4.0;
if (size <= shrMeasure) // make an empty and shrink function
{
Shrink();
}
/*
else if (front == rear)
{
if (front == 0)
front = size - 1;
else
front++;
}
*/
else
{
if (front == size) //brings it full circle
{
front = 0;
}
else
{
front++;
}
}
if (front > capacity)
front = front % capacity;
}
template <class T>
int CDA<T>::Length()
{
return size;
}
template <class T>
int CDA<T>::Capacity()
{
return capacity;
}
template <class T>
int CDA<T>::Clear()
{
~CDA();
size = 1;
circArray[size] = NULL;
}
template <class T>
bool CDA<T>::Ordered()
{
return ordered;
}
template <class T>
int CDA<T>::SetOrdered()
{
for (int i = 1; i < size - 1; i++)
{
if (circArray[(i - 1)] > circArray[i])
{
ordered = false;
return -1;
}
}
ordered = true;
return 1;
}
template <class T>
T CDA<T>::Select(int k)
{
if (ordered == true)
{
return circArray[(front + k - 1) % capacity];
}
else
QuickSelect(front, front + (size - 1), k);
}
template <class T>
int CDA<T>::QSelPartition(int left, int right)
{
int pivot = circArray[right % capacity];
int x = left - 1;
//Swap(&circArray[pivIndex], &circArray[right]);
for (int i = left; i <= right - 1; i++)
{
if (circArray[i % capacity] <= pivot)
{
x++;
Swap(&circArray[x % capacity], &circArray[i % capacity]);
}
}
Swap(&circArray[(x + 1) % capacity], &circArray[right % capacity]);
return (x + 1);
}
template <class T>
T CDA<T>::QuickSelect(int left, int right, int k)
{
if (k > 0 && k <= (right - left) + 1)
{
int index = QSelPartition(left, right);
if (index - 1 == k - 1)
return circArray[index % capacity];
else if (index - 1 > k - 1)
return QuickSelect(left, index - 1, k);
else
return QuickSelect(index - 1, right, k - index + left - 1);
}
return -1;
}
template <class T>
void CDA<T>::InsertionSort() //must be utilized in quicksort
{
for (int i = front + 1; i < (front + size); i++)
{
int val = circArray[i % capacity];
int inc = (i - 1) % capacity;
while (inc >= 0 && circArray[inc] > val)
{
circArray[(inc + 1) % capacity] = circArray[inc];
inc--;
if (inc == -1)
{
inc = capacity - 1;
}
}
circArray[(inc + 1) % capacity] = val;
}
ordered = true;
}
template <class T>
void CDA<T>::QuickSort() // change to other quicksort before leaving the ferg
{
QuickSort1(front, front + (size - 1));
}
template <class T>
void CDA<T>::QuickSort1(int low, int high)
{
while (low < high)
{
if (high - low < 900)
{
InsertionSort();
break;
}
else
{
int pivot = QSortPartition(low, high);
if (pivot - low < high - pivot)
{
QuickSort1(low, pivot--);
low = pivot + 1;
}
else
{
QuickSort1(pivot++, high);
high = pivot - 1;
}
}
}
}
template <class T>
int CDA<T>::QSortPartition(int low, int high)
{
int pivot = circArray[Median(low, high) % capacity];
Swap(&circArray[(Median(low, high)) % capacity], &circArray[(high) % capacity]);
int index = low % capacity;
for (int i = low; i < high; i++)
{
if (circArray[i % capacity] <= pivot)
{
T t = circArray[i % capacity];
circArray[i % capacity] = circArray[index % capacity];
circArray[index % capacity] = t;
index++;
}
}
Swap(&circArray[index % capacity], &circArray[high % capacity]);
return index;
}
template <class T>
int CDA<T>::Median(int low, int high)
{
T left, mid, right;
left = circArray[low % capacity];
mid = circArray[((low + high) / 2) % capacity];
right = circArray[high % high];
if (left < right && left > mid)
return low % capacity;
if (left < mid && left > right)
return low % capacity;
if (right < left && right > mid)
return high % capacity;
if (right < mid && right > left)
return high % capacity;
if (mid < left && mid > right)
return ((low + high) / 2 % capacity);
if (mid < right && mid > left)
return ((low + high) / 2 % capacity);
}
template <class T>
void CDA<T>::Swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
template <class T>
void CDA<T>::CountingSort(int m) ////NEED TO FIX THIS
{
int* OP = new int[size];
int* Counter = new int[m + 1];
for (int i = front; i <= rear; i++)
{
cout << "CircArray[" << i << "] is " << circArray[i] << endl;
}
for (int i = 0; i <= m; i++)
{
Counter[i] = 0;
}
for (int i = front; i < front + (size); i++)
{
Counter[circArray[i % capacity]]++;
}
for (int i = 1; i <= m; i++)
{
Counter[i] += Counter[i - 1];
}
for (int i = rear - 1; i > 0; i--)
{
OP[Counter[circArray[i]] - 1] = circArray[i];
cout << "Circular array at " << i << " is " << circArray[i] << endl;
Counter[circArray[i]] -= 1;
if (i == front % capacity)
break;
if (i == 0)
i = capacity;
}
for (int i = 0; i < size; i++)
circArray[i] = OP[i];
ordered = true;
front = 0;
}
template <class T>
int CDA<T>::Search(T e)
{
if (ordered == true) //binary search of item e
{
return BinarySearch(front, front + (size - 1), e);
}
else if (ordered == false)
{
for (int i = 0; i < size - 1; i++)
{
if (circArray[i] == e)
return i;
}
}
return -1;
}
template <class T>
int CDA<T>::BinarySearch(int left, int right, T e)
{
while (left <= right)
{
int mid = (left + right) / 2;
int value = circArray[mid % capacity];
if (value == e)
return (mid - front) % capacity;
else if (value < e)
return BinarySearch(mid + 1, right, e);
else if (value > e)
return BinarySearch(left, mid - 1, e);
}
return -1;
}
template <class T>
void CDA<T>::reSize()
{
capacity = capacity * 2;
T *nArray = new T[capacity];
for (int i = 0; i < size - 1; i++)
{
int l = (front + i) % (size-1);
nArray[i] = circArray[l];
}
//delete[]circArray;
circArray = nArray;
front = 0;
rear = (size - 1);
}
template <class T>
void CDA<T>::Shrink()
{
int tFront = front;
capacity = capacity / 2;
T* bArr = new T[capacity];
int index = 0;
while (front <= rear)
{
bArr[index] = circArray[(front + index) % capacity];
index++;
}
T* circArray = bArr;
front = 0;
rear = (size - 1);
}
template <class T>
CDA<T>& CDA<T>::operator=(const CDA<T>& a)
{
if (this != &a)
{
delete[]circArray;
size = a.size;
capacity = a.capacity;
circArray = new T[a.capacity];
front = a.front;
rear = a.size - 1;
ordered = a.ordered;
for (int i = a.front; i < a.front + (a.size); i++)
{
circArray[i % capacity] = a.circArray[i % capacity];
}
}
return *this;
}
template <class T>
int CDA<T>::Front()
{
return front;
}
template <class T>
T CDA<T>::Data(int n)
{
return circArray[n];
}
#include <iostream>
#include "CDA-1.cpp"
using namespace std;
template<class keytype, class valuetype>
class Heap
{
private:
CDA<keytype>* K;
CDA<valuetype>* V;
int size;
public:
Heap()
{
this->K = new CDA<keytype>();
this->V = new CDA<valuetype>();
size = 0;
}
Heap(keytype k[], valuetype v[], int s)
{
//allocate two different arrays for each type
//fill those arrays concurrently using insert
//sort concurrently using heapafy recursively
this->K = new CDA<keytype>(s);
this->V = new CDA<valuetype>(s);
this->size = s;
for (int i = 0; i < s; i++)
{
insert(k[i], v[i]);
}
heapify(s, K->Front());
}
void heapify(int s, int i)
{
//Errors for evans to fix: swap the n's with s.
//Fix the left and right variable logic. Hepaify smallest not small at the bottom.
//Also we need to pass V[] in a parameter so we can edit it in this.
//How to better swap V with K and not just K.
int smallest = i;
int left = 2*i +(-i+1);
int right = 2*i + (-i+2);
keytype kl = K->Data(left);
keytype kr = K->Data(right);
keytype ks = K->Data(smallest);
if (left < s && kl < ks) //FIX
smallest = left;
if (right < s && kr < ks) //FIX
smallest = right;
if (smallest != i)
{
swap(K[i], K[smallest]);
swap(V[i], V[smallest]); //FIX
heapify(s, smallest);
}
}
~Heap() {
return;
}
//items should be inserted using bottom up heap building method
void insert(keytype k, valuetype v)
{
K->AddEnd(k);
V->AddEnd(v);
heapify(size, K->Front());
}
keytype peekKey()
{
int f = K->Front();
return K->Data(f);
}
valuetype peekValue()
{
int f = V->front();
return V->Data(f);
}
keytype extractMin()
{
keytype temp = K->Data(K->Front());
K->DelFront();
V->DelFront();
heapify(size, K->Front());
return temp;
}
void printKey()
{
ActualPrintKey(K->Front());
}
void ActualPrintKey(int n)
{
keytype rt = K->Data(n);
if (rt != size)
{
cout << K->Data(rt) << " ";
ActualPrintKey((2 * n) + (-n + 1));
ActualPrintKey((2 * n) + (-n + 2));
}
}
};
/*
template <class keytype, class valuetype>
class BHeap
{
BHeap();
BHeap(keytype k[], valuetype v[], int s);
~BHeap();
keytype peekKey();
valuetype peekValue();
keytype extractMin();
//items should be inserted using repeated insertion
void insert(keytype k, valuetype v);
void merge(BHeap<keytype, valuetype>& H2);
void printKey();
};
*/
#include <iostream>
#include "Heaps.cpp"
using namespace std;
int main() {
string K[10] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "K" };
int V[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
Heap<string, int> T1, T2(K, V, 10);
cout << T2.peekKey() << endl;
cout << endl;
system("pause");
return 0;
}
In general "Access violation reading location", means you are trying to read virtually memory address space to a process which does not belong to your application and the operating system protective mechanism is kicking in to protect the rest of the loaded applications and resource from been accessed (read or write) by your application "memory leak vulnerability". If I was at your place I would review the code and all variables and arrays if they are properly initialized before use. Another thing which needs to be taken in consideration is the operating system and the permissions required by your application (Windows run as Administrator / GNU/Linux sudo).
Cheers

Comparing Execution time with Time Complexity in Merge & Quick Sort

I have implemented Merge & Quick Sort in the textbook what I've learned, and it says Time Complexities of each sorts are like this:
Merge Sort: O(n.log(n)) / Quick Sort: average O(n.log(n)) and O(n2) in the worst case (if key array is sorted).
So I executed the programs with Two types of Arrays: sorted and random, with different sizes.
Since I wanted to get the Average time, I have tried 10 times per each case.
Here is the code of Merge & Quick Sort:
#include <iostream>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
void Merge(vector<int>& s, int low, int mid, int high) {
int i = low;
int j = mid + 1;
int k = low;
vector<int> u(s);
while (i <= mid && j <= high) {
if (s.at(i) < s.at(j)) {
u.at(k) = s.at(i);
i++;
} else {
u.at(k) = s.at(j);
j++;
}
k++;
}
if (i > mid) {
for (int a = j; a < high + 1; a++) {
u.at(k) = s.at(a);
k++;
}
} else {
for (int a = i; a < mid + 1; a++) {
u.at(k) = s.at(a);
k++;
}
}
for (int a = low; a < high + 1; a++)
s.at(a) = u.at(a);
}
void MergeSort(vector<int>& s, int low, int high) {
int mid;
if (low < high) {
mid = (low + high) / 2;
MergeSort(s, low, mid);
MergeSort(s, mid + 1, high);
Merge(s, low, mid, high);
}
}
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
void Partition(vector<int>& s, int low, int high, int& pvpoint) {
int j;
int pvitem;
pvitem = s.at(low);
j = low;
for (int i = low + 1; i <= high; i++) {
if (s.at(i) < pvitem) {
j++;
swap(s.at(i), s.at(j));
}
pvpoint = j;
swap(s.at(low), s.at(pvpoint));
}
}
void QuickSort(vector<int>& s, int low, int high) {
int pvpoint;
if (high > low) {
Partition(s, low, high, pvpoint);
QuickSort(s, low, pvpoint - 1);
QuickSort(s, pvpoint + 1, high);
}
}
And each of these main() functions are printing the execution times in SORTED, and RANDOM key arrays.
you can see the result with adding one of these main functions in Visual Studio(C++):
//Sorted key array
int main() {
int s;
for (int i = 1; i < 21; i++) { //Size is from 300 to 6000
s = i * 300;
vector<int> Arr(s);
cout << "N : " << s << "\n";
//Assign Random numbers to each elements
Arr.front() = rand() % Arr.size();
for (int j = 1; j < Arr.size(); j++) { Arr.at(j) = ((737 * Arr.at(j - 1) + 149) % (Arr.size() * 5)); }
sort(Arr.begin(), Arr.end());
//QuickSort(Arr, 0, Arr.size() - 1); <- you can switch using this instead of MergeSort(...) below
for (int i = 0; i < 10; i++) { //print 10 times of execution time
clock_t start, end;
start = clock();
MergeSort(Arr, 0, Arr.size() - 1);
end = clock() - start;
printf("%12.3f ", (double)end * 1000.0 / CLOCKS_PER_SEC);
}
cout << endl;
}
return 0;
}
//Random key array
int main() {
int s;
for (int i = 1; i < 21; i++) {
s = i * 3000;
vector<int> Arr(s);
cout << "N : " << s << "\n";
for (int i = 0; i < 10; i++) {
//Assign Random numbers to each elements
Arr.front() = rand() % Arr.size();
for (int j = 1; j < Arr.size(); j++) { Arr.at(j) = ((737 * Arr.at(j - 1) + 149) % (Arr.size() * 5)); }
//QuickSort(Arr, 0, Arr.size() - 1); <- you can switch using this instead of MergeSort(...) below
clock_t start, end;
start = clock();
MergeSort(Arr, 0, Arr.size() - 1);
end = clock() - start;
printf("%12.3f ", (double)end * 1000.0 / CLOCKS_PER_SEC);
}
cout << endl;
}
return 0;
}
And the THING is, the result is not matching with their time complexity. for example, Merge sort in(RANDOM Array)
size N=3000 prints 20 ms, but size N=60000 prints 1400~1600 ms !! it supposed to print almost 400 ms because Time complexity (Not in worse case) in Quick Sort is O(n.log(n)), isn't it? I want to know what affects to this time and how could I see the printed time that I expected.
You posted the same code in this question: Calculate Execution Times in Sort algorithm and you did not take my answer into account.
Your MergeSort function has a flaw: you duplicate the whole array in merge causing a lot of overhead and quadratic time complexity. This innocent looking definition: vector<int> u(s); defines u as a vector initialized as a copy of s, the full array.
C++ is a very powerful language, often too powerful, littered with traps and pitfalls such as this. It is a very good thing you tried to verify that your program meets the expected performance from the known time complexity of the algorithm. Such a concern is alas too rare.
Here are some guidelines:
For getting execution time:
#include <time.h>
int main()
{
struct timeval stop, start;
int arr[10000];
gettimeofday(&start, NULL);
mergeSort(arr, 0, 9999);
gettimeofday(&stop, NULL);
printf("Time taken for Quick sort is: %ld microseconds\n",
(stop.tv_sec-start.tv_sec)*1000000+stop.tv_usec-start.tv_usec);
}

What is the time complexity of this function?

Here's a sample solution for Sliding Window Maximum problem in Java.
Given an array nums, there is a sliding window of size k which is
moving from the very left of the array to the very right. You can only
see the k numbers in the window. Each time the sliding window moves
right by one position.
I want to get the time and space complexity of this function. Here's what I think would be the answer:
Time: O((n-k)(k * logk)) == O(nklogk)
Space (auxiliary): O(n) for return int[] and O(k) for pq. Total of O(n).
Is this correct?
private static int[] maxSlidingWindow(int[] a, int k) {
if(a == null || a.length == 0) return new int[] {};
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
// max heap
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int[] result = new int[a.length - k + 1];
int count = 0;
// time: n - k times
for (int i = 0; i < a.length - k + 1; i++) {
for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
// logk
result[count] = pq.poll();
count = count + 1;
pq.clear();
}
return result;
}
You're right in most of the part except -
for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
Here total number of executions is log1 + log2 + log3 + log4 + ... + logk. The summation of this series -
log1 + log2 + log3 + log4 + ... + logk = log(k!)
And second thought is, you can do it better than your linearithmic time solution using double-ended queue property which will be O(n). Here is my solution -
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || k <= 0) {
return new int[0];
}
int n = nums.length;
int[] result = new int[n - k + 1];
int indx = 0;
Deque<Integer> q = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
// remove numbers out of range k
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll();
}
// remove smaller numbers in k range as they are useless
while (!q.isEmpty() && nums[q.peekLast()] < nums[i]) {
q.pollLast();
}
q.offer(i);
if (i >= k - 1) {
result[indx++] = nums[q.peek()];
}
}
return result;
}
HTH.

QuadTree or KD Tree for objective c? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I'm looking a while for a decent piece of code to use in my app, in one of those algorithms.
I found this example: http://rosettacode.org/wiki/K-d_tree#C
But when I put the code in xcode, I get an errors, for example:
"use of undeclared identifier", "expected ';' at the end of declaration".
I guess a header file is missing?
I copied the code from the link and made a minor edit which moved
"swap" from being an inline nested function to a static function.
Compiled with "gcc -C99 file.c" and it compiled ok. So, no, it doesn't
need some include file. Maybe you mis pasted it.
If you are happy with this answer, you could accept it. Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define MAX_DIM 3
struct kd_node_t{
double x[MAX_DIM];
struct kd_node_t *left, *right;
};
inline double
dist(struct kd_node_t *a, struct kd_node_t *b, int dim)
{
double t, d = 0;
while (dim--) {
t = a->x[dim] - b->x[dim];
d += t * t;
}
return d;
}
static void swap(struct kd_node_t *x, struct kd_node_t *y) {
double tmp[MAX_DIM];
memcpy(tmp, x->x, sizeof(tmp));
memcpy(x->x, y->x, sizeof(tmp));
memcpy(y->x, tmp, sizeof(tmp));
}
/* see quickselect method */
struct kd_node_t*
find_median(struct kd_node_t *start, struct kd_node_t *end, int idx)
{
if (end <= start) return NULL;
if (end == start + 1)
return start;
struct kd_node_t *p, *store, *md = start + (end - start) / 2;
double pivot;
while (1) {
pivot = md->x[idx];
swap(md, end - 1);
for (store = p = start; p < end; p++) {
if (p->x[idx] < pivot) {
if (p != store)
swap(p, store);
store++;
}
}
swap(store, end - 1);
/* median has duplicate values */
if (store->x[idx] == md->x[idx])
return md;
if (store > md) end = store;
else start = store;
}
}
struct kd_node_t*
make_tree(struct kd_node_t *t, int len, int i, int dim)
{
struct kd_node_t *n;
if (!len) return 0;
if ((n = find_median(t, t + len, i))) {
i = (i + 1) % dim;
n->left = make_tree(t, n - t, i, dim);
n->right = make_tree(n + 1, t + len - (n + 1), i, dim);
}
return n;
}
/* global variable, so sue me */
int visited;
void nearest(struct kd_node_t *root, struct kd_node_t *nd, int i, int dim,
struct kd_node_t **best, double *best_dist)
{
double d, dx, dx2;
if (!root) return;
d = dist(root, nd, dim);
dx = root->x[i] - nd->x[i];
dx2 = dx * dx;
visited ++;
if (!*best || d < *best_dist) {
*best_dist = d;
*best = root;
}
/* if chance of exact match is high */
if (!*best_dist) return;
if (++i >= dim) i = 0;
nearest(dx > 0 ? root->left : root->right, nd, i, dim, best, best_dist);
if (dx2 >= *best_dist) return;
nearest(dx > 0 ? root->right : root->left, nd, i, dim, best, best_dist);
}
#define N 1000000
#define rand1() (rand() / (double)RAND_MAX)
#define rand_pt(v) { v.x[0] = rand1(); v.x[1] = rand1(); v.x[2] = rand1(); }
int main(void)
{
int i;
struct kd_node_t wp[] = {
{{2, 3}}, {{5, 4}}, {{9, 6}}, {{4, 7}}, {{8, 1}}, {{7, 2}}
};
struct kd_node_t this = {{9, 2}};
struct kd_node_t *root, *found, *million;
double best_dist;
root = make_tree(wp, sizeof(wp) / sizeof(wp[1]), 0, 2);
visited = 0;
found = 0;
nearest(root, &this, 0, 2, &found, &best_dist);
printf(">> WP tree\nsearching for (%g, %g)\n"
"found (%g, %g) dist %g\nseen %d nodes\n\n",
this.x[0], this.x[1],
found->x[0], found->x[1], sqrt(best_dist), visited);
million = calloc(N, sizeof(struct kd_node_t));
srand(time(0));
for (i = 0; i < N; i++) rand_pt(million[i]);
root = make_tree(million, N, 0, 3);
rand_pt(this);
visited = 0;
found = 0;
nearest(root, &this, 0, 3, &found, &best_dist);
printf(">> Million tree\nsearching for (%g, %g, %g)\n"
"found (%g, %g, %g) dist %g\nseen %d nodes\n",
this.x[0], this.x[1], this.x[2],
found->x[0], found->x[1], found->x[2],
sqrt(best_dist), visited);
/* search many random points in million tree to see average behavior.
tree size vs avg nodes visited:
10 ~ 7
100 ~ 16.5
1000 ~ 25.5
10000 ~ 32.8
100000 ~ 38.3
1000000 ~ 42.6
10000000 ~ 46.7 */
int sum = 0, test_runs = 100000;
for (i = 0; i < test_runs; i++) {
found = 0;
visited = 0;
rand_pt(this);
nearest(root, &this, 0, 3, &found, &best_dist);
sum += visited;
}
printf("\n>> Million tree\n"
"visited %d nodes for %d random findings (%f per lookup)\n",
sum, test_runs, sum/(double)test_runs);
// free(million);
return 0;
}

Omaha Hi Hand Evaluator

Currently I'm trying to port Keith Rule's Texas Holdem Hand Evaluator to Omaha Hi:
Texas Holdem Evaluator and Analysis
More Analysis Part1
More Analysis Part 2
After thinking more about the algorithm, I found a solution which gives me the right percentages for the hands and everything is fine..
But it's really really slow. How can I speed things up?
As the only thing I do right now is to look-up a normal five card hands, a LUT might be right for me. Anyone integrated one before?
static void Main(string[] args)
{
long count = 0;
double player1win = 0.0, player2win=0.0;
ulong player1 = Hand.ParseHand("Ad Kd As Ks");
ulong player2 = Hand.ParseHand("Th 5c 2c 7d");
foreach (ulong board in Hand.Hands(0, player1 | player2, 5))
{
uint maxplayer1value = 0, maxplayer2value = 0;
foreach (ulong boardcards in Hand.Hands(0, ulong.MaxValue ^ board, 3))
{
foreach (ulong player1hand in Hand.Hands(0Ul, ulong.MaxValue ^ player1, 2))
{
uint player1value = Hand.Evaluate(player1hand | boardcards, 5);
if (player1value > maxplayer1value) maxplayer1value = player1value;
}
}
foreach (ulong boardcards in Hand.Hands(0, ulong.MaxValue ^ board, 3))
{
foreach (ulong player2hand in Hand.Hands(0UL, ulong.MaxValue ^ player2, 2))
{
uint player2value = Hand.Evaluate(player2hand | boardcards, 5);
if (player2value > maxplayer2value) maxplayer2value = player2value;
}
}
if (maxplayer1value > maxplayer2value)
{
player1win += 1.0;
}
else if (maxplayer2value > maxplayer1value)
{
player2win += 1.0;
}
else
{
player1win += 0.5;
player2win += 0.5;
}
count++;
}
Console.WriteLine("Player1: {0:0.0000} Player2: {1:0.0000} Count: {2}", player1win / count * 100, player2win / count * 100, count);
Console.ReadLine();
}
Looks like you're trying to create equity calculator. I've done this as well, but not for Omaha (Texas Hold'em instead). With then players to evaluate, I've got about ~200K hands per second, which gives accurate result enough in no time. If there only two players to
evaluate, I can get up to 4 million evaluations per second.
I used bitmasks for hands. One 64-bit integer to represent card, hand or entire board. You only need actually 52 of it, obviously. By using bitwise-operators, things get going rather quickly. Here's a quick sample from my project (in C++ tho). It's using 2 + 2 evaluator
for fast look-ups:
while (trial < trials) {
/** I use here a linked list over the hand-distributions (players).
* This is kind of natural as well, as circle is the basic
* shape of poker.
*/
pDist = pFirstDist;
unsigned __int64 usedCards = _deadCards;
bool collision;
/** Here, we choose random distributions for the comparison.
* There is a chance, that two separate distributions has
* the same card being picked-up. In that case, we have a collision,
* so do the choosing again.
*/
do {
pDist->Choose(usedCards, collision);
/** If there is only one hand in the distribution (unary),
* there is no need to check over collision, since it's been
* already done in the phase building them (distributions).
*/
if (pDist->_isUnary)
collision = false;
pDist = pDist->_pNext;
} while (pDist != pFirstDist && !collision);
if (collision) {
/** Oops! Collision occurred! Take the next player (hand-
* distribution and do this all over again.
*
*/
pFirstDist = pDist->_pNext;
continue;
}
unsigned __int64 board = 0;
/** Pick a board from the hashed ones, until it's unique compared to
* the distributions.
*
*/
do {
if (count == 1) {
board = boards[0];
collision = false;
} else {
board = boards[Random()];
collision = (board & usedCards) != 0;
}
} while (collision);
board |= _boardCards;
int best = 0, s = 1;
do {
pDist->_currentHand |= board;
unsigned long i, l = static_cast<unsigned long>(pDist->_currentHand >> 32);
int p;
bool f = false;
/** My solution to find out the set bits.
* Since I'm working on a 32-bit environment, the "64-bit"
* variable needs to be split in to parts.
*/
if (_BitScanForward(&i, l)) {
p = _evaluator->_handRanks[53 + i + 32]; // Initial entry to the 2 + 2 evaluator hash.
l &= ~(static_cast<unsigned long>(1) << i);
f = true;
}
if (f)
while (_BitScanForward(&i, l)) {
l &= ~(static_cast<unsigned long>(1) << i);
p = _evaluator->_handRanks[p + i + 32];
}
l = static_cast<unsigned long>(pDist->_currentHand & 0xffffffff);
if (!f) {
_BitScanForward(&i, l);
p = _evaluator->_handRanks[53 + i];
l &= ~(static_cast<unsigned long>(1) << i);
}
while (_BitScanForward(&i, l)) {
l &= ~(static_cast<unsigned long>(1) <<_handRanks[p + i];
}
pDist->_rank = p;
/** Keep the statistics up. Please do remember, that
* equity consist of ties as well, so it's not a percentual
* chance of winning.
*/
if (p > best) {
pWinner = pDist;
s = 1;
best = p;
} else if (p == best)
++s;
pDist = pDist->_pNext;
} while (pDist != pFirstDist);
if (s > 1) {
for (unsigned int i = 0; i _rank == best) {
_handDistributions[i]->_ties += 1.0f / s;
_handDistributions[i]->_equity += 1.0f / s;
}
} else {
++pWinner->_wins;
++pWinner->_equity;
}
++trial;
pFirstDist = pDist->_pNext;
}
Please refer to the 2 + 2 evaluator, which is quite easy to adapt in your own needs.
This might help:
An example of a ready made Objective-C (and Java) Texas Hold'em 7- and 5-card evaluator can be found here and further explained here. It "adds" up hands to generate an index that sufficiently characterises the hand for determining rank.
All feedback welcome at the e-mail address found therein