/* NiuTrans.Tensor - an open-source tensor library * Copyright (C) 2017, Natural Language Processing Lab, Northestern University. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * * Implementation of list that keeps data items * * $Created by: XIAO Tong (xiaotong@mail.neu.edu.cn) 2018-04-17 * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "XList.h" #include "XGlobal.h" #include "wchar.h" #include "locale.h" #if !defined( WIN32 ) && !defined( _WIN32 ) #include "sys/time.h" #include "time.h" #include "iconv.h" #else #include "time.h" #endif /* the nts (NiuTrans.Tensor) namespace */ namespace nts{ XList NULLList; /* constructor */ XList::XList() { mem = NULL; maxNum = 8; count = 0; items = new void*[8]; isIntList = false; } /* constructor >> myMaxNum - maximum number of items to keep >> isIntListOrNot - specify if the list keeps int items */ XList::XList(int myMaxNum, bool isIntListOrNot) { mem = NULL; maxNum = myMaxNum; count = 0; items = new void*[myMaxNum]; isIntList = isIntListOrNot; } /* constructor >> myMaxNum - maximum number of items to keep >> myMem - the memory pool used for data allocation >> isIntListOrNot - specify if the list keeps int items */ XList::XList(int myMaxNum, XMem * myMem, bool isIntListOrNot) { mem = myMem; maxNum = myMaxNum; count = 0; items = (void**)mem->Alloc(mem->devID, sizeof(void*) * maxNum); isIntList = isIntListOrNot; } /* de-constructor */ XList::~XList() { if(isIntList){ for(int i = 0; i < count; i++){ int * p = (int*)items[i]; delete[] p; } } if(mem == NULL) delete[] items; } /* allocate the data array for the list >> myMaxNum - maximum number of items to keep >> isIntListOrNot - specify if the list keeps int items */ void XList::Create(int myMaxNum, XMem * myMem) { mem = myMem; maxNum = myMaxNum; count = 0; items = (void**)mem->Alloc(mem->devID, sizeof(void*) * maxNum); } /* add an item into the list >> item - pointer to the item */ void XList::Add(const void * item) { if( count == maxNum ){ void ** newItems; if( mem == NULL ) newItems = new void*[maxNum * 2 + 1]; else newItems = (void**)mem->Alloc(mem->devID, sizeof(void*) * (maxNum * 2 + 1)); memcpy(newItems, items, sizeof(void*) * maxNum); if( mem == NULL ) delete[] items; items = newItems; maxNum = maxNum * 2 + 1; } MTYPE p = (MTYPE)item; items[count++] = (MTYPE*)p; } /* add a number of items into the list >> inputItems - pointer to the array of items >> inputItemCount - number of input items */ void XList::Add(void ** inputItems, int inputItemCount) { if( count + inputItemCount >= maxNum ){ int newMaxNum = (count + inputItemCount) * 2 + 1; void ** newItems; if( mem == NULL ) newItems = new void*[newMaxNum]; else newItems = (void**)mem->Alloc(mem->devID, sizeof(void*) * newMaxNum); memcpy(newItems, items, sizeof(void*) * maxNum); if( mem == NULL ) delete[] items; items = newItems; maxNum = newMaxNum; } memcpy(items + count, inputItems, sizeof(void*) * inputItemCount); count += inputItemCount; } /* append a list to the current list >> l - the list we use to append */ void XList::AddList(XList * l) { Add(l->items, l->count); } /* add an integer-typed item into the list >> item - pointer to the item */ void XList::AddInt(int i) { CheckNTErrors(isIntList, "An int list is required!"); int * a = new int[1]; *a = i; Add(a); } /* insert an item to the given position of the list >> pos - the position >> item - the item for insertion */ void XList::Insert(int pos, void * item) { if( count == maxNum ){ void ** newItems; if( mem == NULL ) newItems = new void*[maxNum * 2 + 1]; else newItems = (void**)mem->Alloc(mem->devID, sizeof(void*) * (maxNum * 2 + 1)); memcpy(newItems, items, sizeof(void*) * maxNum); if( mem == NULL ) delete[] items; items = newItems; maxNum = maxNum * 2 + 1; } for(int i = count - 1; i >= pos; i--) items[i + 1] = items[i]; items[pos] = item; count++; } /* get the item at position i */ void * XList::GetItem(int i) const { CheckNTErrors(i >= -1 && i < count, "Index of a list item is out of scope!"); CheckNTErrors(count > 0, "Cannt index the item in an empty list!"); if(i == -1) return items[count - 1]; else return items[i]; } /* get the integer-typed item at position i */ int XList::GetItemInt(int i) { CheckNTErrors(isIntList, "An int list is required!"); CheckNTErrors(i >= 0 && i < count, "Index of a list item is out of scope!"); return *(int*)(items[i]); } /* set the item at position i */ void XList::SetItem(int i, void * item) { if( i >= 0 && i < count ) items[i] = item; } /* get the integer-typed item at position i */ void XList::SetItemInt(int i, int item) { CheckNTErrors(isIntList, "An int list is required!"); if( i >= 0 && i < count ) *(int*)(items[i]) = item; } /* find the position of the first matched item >> item - the item for matching << the position where we hit the item (if any) */ int XList::FindFirst(void * item) { for(int i = 0;i < count; i++){ if(item == items[i]) return i; } return -1; } /* clear the data array */ void XList::Clear() { if(isIntList){ for(int i = 0; i < count; i++){ delete[] (int*)items[i]; } count = 0; } else count = 0; } /* delete the data array as well as the string arrays kept in it */ void XList::ClearStringList() { if(mem == NULL){ for(int i = 0; i < count; i++){ delete[] (char*)items[i]; } } count = 0; } /* sort the list >> itemSize - size of an item >> comp - the comparison function used in sorting */ void XList::Sort(int itemSize, ListCompare comp) { qsort(items, count, itemSize, comp); } /* reverse the list */ void XList::Reverse() { int half = count/2; for(int i = 0; i < half; i++){ void * tmp = items[i]; items[i] = items[count - i - 1]; items[count - i - 1] = tmp; } } /* remove the item at position i */ void XList::Remove(int i) { if(i >= count || i < 0) return; memcpy(items + i, items + i + 1, sizeof(void*) * (count - i - 1)); count--; } /* copy the list >> myMem - memory pool used for allocating the data in the new list << hard copy of the list */ XList * XList::Copy(XMem * myMem) { XList * newList = new XList(maxNum, myMem); for(int i = 0; i < count; i++){ newList->Add(GetItem(i)); } return newList; } /* shuffle the list >> nround - number of rounds for shuffling >> beg - where we start >> len - how many items are used in shuffling */ void XList::Shuffle(int nround, int beg, int len) { if(beg < 0){ beg = 0; len = count; } if(beg + len > count) return; srand((unsigned int)time(NULL)); for(int k = 0; k < nround; k++){ /* Fisher�CYates shuffle */ for(int i = 0; i < len; i++){ float a = (float)rand()/RAND_MAX; size_t j = (unsigned int) (a*(i+1)); void* t = items[beg + j]; items[beg + j] = items[beg + i]; items[beg + i] = t; } } } } /* end of the nts (NiuTrans.Tensor) namespace */