00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #define _SORTFUN_SOURCE_
00027
00028 #include "setup.h"
00029
00030 #include "argacces.h"
00031 #include "dffnxfun.h"
00032 #include "envrnmnt.h"
00033 #include "evaluatn.h"
00034 #include "extnfunc.h"
00035 #include "memalloc.h"
00036 #include "multifld.h"
00037 #include "sysdep.h"
00038
00039 #include "sortfun.h"
00040
00041 #define SORTFUN_DATA 7
00042
00043 struct sortFunctionData
00044 {
00045 struct expr *SortComparisonFunction;
00046 };
00047
00048 #define SortFunctionData(theEnv) ((struct sortFunctionData *) GetEnvironmentData(theEnv,SORTFUN_DATA))
00049
00050
00051
00052
00053
00054 static void DoMergeSort(void *,DATA_OBJECT *,DATA_OBJECT *,unsigned long,
00055 unsigned long,unsigned long,unsigned long,
00056 int (*)(void *,DATA_OBJECT *,DATA_OBJECT *));
00057 static int DefaultCompareSwapFunction(void *,DATA_OBJECT *,DATA_OBJECT *);
00058 static void DeallocateSortFunctionData(void *);
00059
00060
00061
00062
00063
00064 globle void SortFunctionDefinitions(
00065 void *theEnv)
00066 {
00067 AllocateEnvironmentData(theEnv,SORTFUN_DATA,sizeof(struct sortFunctionData),DeallocateSortFunctionData);
00068 #if ! RUN_TIME
00069 EnvDefineFunction2(theEnv,"sort",'u', PTIEF SortFunction,"SortFunction","1**w");
00070 #endif
00071 }
00072
00073
00074
00075
00076
00077 static void DeallocateSortFunctionData(
00078 void *theEnv)
00079 {
00080 ReturnExpression(theEnv,SortFunctionData(theEnv)->SortComparisonFunction);
00081 }
00082
00083
00084
00085
00086 static int DefaultCompareSwapFunction(
00087 void *theEnv,
00088 DATA_OBJECT *item1,
00089 DATA_OBJECT *item2)
00090 {
00091 DATA_OBJECT returnValue;
00092
00093 SortFunctionData(theEnv)->SortComparisonFunction->argList = GenConstant(theEnv,item1->type,item1->value);
00094 SortFunctionData(theEnv)->SortComparisonFunction->argList->nextArg = GenConstant(theEnv,item2->type,item2->value);
00095 ExpressionInstall(theEnv,SortFunctionData(theEnv)->SortComparisonFunction);
00096 EvaluateExpression(theEnv,SortFunctionData(theEnv)->SortComparisonFunction,&returnValue);
00097 ExpressionDeinstall(theEnv,SortFunctionData(theEnv)->SortComparisonFunction);
00098 ReturnExpression(theEnv,SortFunctionData(theEnv)->SortComparisonFunction->argList);
00099 SortFunctionData(theEnv)->SortComparisonFunction->argList = NULL;
00100
00101 if ((GetType(returnValue) == SYMBOL) &&
00102 (GetValue(returnValue) == EnvFalseSymbol(theEnv)))
00103 { return(FALSE); }
00104
00105 return(TRUE);
00106 }
00107
00108
00109
00110
00111
00112 globle void SortFunction(
00113 void *theEnv,
00114 DATA_OBJECT_PTR returnValue)
00115 {
00116 long argumentCount, i, j, k = 0;
00117 DATA_OBJECT *theArguments, *theArguments2;
00118 DATA_OBJECT theArg;
00119 struct multifield *theMultifield, *tempMultifield;
00120 char *functionName;
00121 struct expr *functionReference;
00122 int argumentSize = 0;
00123 struct FunctionDefinition *fptr;
00124 #if DEFFUNCTION_CONSTRUCT
00125 DEFFUNCTION *dptr;
00126 #endif
00127
00128
00129
00130
00131
00132 SetpType(returnValue,SYMBOL);
00133 SetpValue(returnValue,EnvFalseSymbol(theEnv));
00134
00135
00136
00137
00138
00139 if ((argumentCount = EnvArgCountCheck(theEnv,"sort",AT_LEAST,1)) == -1)
00140 { return; }
00141
00142
00143
00144
00145
00146 if (EnvArgTypeCheck(theEnv,"sort",1,SYMBOL,&theArg) == FALSE)
00147 { return; }
00148
00149 functionName = DOToString(theArg);
00150 functionReference = FunctionReferenceExpression(theEnv,functionName);
00151 if (functionReference == NULL)
00152 {
00153 ExpectedTypeError1(theEnv,"sort",1,"function name, deffunction name, or defgeneric name");
00154 return;
00155 }
00156
00157
00158
00159
00160
00161
00162 if (functionReference->type == FCALL)
00163 {
00164 fptr = (struct FunctionDefinition *) functionReference->value;
00165 if ((GetMinimumArgs(fptr) > 2) ||
00166 (GetMaximumArgs(fptr) == 0) ||
00167 (GetMaximumArgs(fptr) == 1))
00168 {
00169 ExpectedTypeError1(theEnv,"sort",1,"function name expecting two arguments");
00170 ReturnExpression(theEnv,functionReference);
00171 return;
00172 }
00173 }
00174
00175
00176
00177
00178
00179
00180 #if DEFFUNCTION_CONSTRUCT
00181 if (functionReference->type == PCALL)
00182 {
00183 dptr = (DEFFUNCTION *) functionReference->value;
00184 if ((dptr->minNumberOfParameters > 2) ||
00185 (dptr->maxNumberOfParameters == 0) ||
00186 (dptr->maxNumberOfParameters == 1))
00187 {
00188 ExpectedTypeError1(theEnv,"sort",1,"deffunction name expecting two arguments");
00189 ReturnExpression(theEnv,functionReference);
00190 return;
00191 }
00192 }
00193 #endif
00194
00195
00196
00197
00198
00199
00200 if (argumentCount == 1)
00201 {
00202 EnvSetMultifieldErrorValue(theEnv,returnValue);
00203 ReturnExpression(theEnv,functionReference);
00204 return;
00205 }
00206
00207
00208
00209
00210
00211
00212 theArguments = (DATA_OBJECT *) genalloc(theEnv,(argumentCount - 1) * sizeof(DATA_OBJECT));
00213
00214 for (i = 2; i <= argumentCount; i++)
00215 {
00216 EnvRtnUnknown(theEnv,i,&theArguments[i-2]);
00217 if (GetType(theArguments[i-2]) == MULTIFIELD)
00218 { argumentSize += GetpDOLength(&theArguments[i-2]); }
00219 else
00220 { argumentSize++; }
00221 }
00222
00223 if (argumentSize == 0)
00224 {
00225 genfree(theEnv,theArguments,(argumentCount - 1) * sizeof(DATA_OBJECT));
00226 EnvSetMultifieldErrorValue(theEnv,returnValue);
00227 ReturnExpression(theEnv,functionReference);
00228 return;
00229 }
00230
00231
00232
00233
00234
00235
00236 theArguments2 = (DATA_OBJECT *) genalloc(theEnv,argumentSize * sizeof(DATA_OBJECT));
00237
00238 for (i = 2; i <= argumentCount; i++)
00239 {
00240 if (GetType(theArguments[i-2]) == MULTIFIELD)
00241 {
00242 tempMultifield = (struct multifield *) GetValue(theArguments[i-2]);
00243 for (j = GetDOBegin(theArguments[i-2]); j <= GetDOEnd(theArguments[i-2]); j++, k++)
00244 {
00245 SetType(theArguments2[k],GetMFType(tempMultifield,j));
00246 SetValue(theArguments2[k],GetMFValue(tempMultifield,j));
00247 }
00248 }
00249 else
00250 {
00251 SetType(theArguments2[k],GetType(theArguments[i-2]));
00252 SetValue(theArguments2[k],GetValue(theArguments[i-2]));
00253 k++;
00254 }
00255 }
00256
00257 genfree(theEnv,theArguments,(argumentCount - 1) * sizeof(DATA_OBJECT));
00258
00259 functionReference->nextArg = SortFunctionData(theEnv)->SortComparisonFunction;
00260 SortFunctionData(theEnv)->SortComparisonFunction = functionReference;
00261
00262 for (i = 0; i < argumentSize; i++)
00263 { ValueInstall(theEnv,&theArguments2[i]); }
00264
00265 MergeSort(theEnv,(unsigned long) argumentSize,theArguments2,DefaultCompareSwapFunction);
00266
00267 for (i = 0; i < argumentSize; i++)
00268 { ValueDeinstall(theEnv,&theArguments2[i]); }
00269
00270 SortFunctionData(theEnv)->SortComparisonFunction = SortFunctionData(theEnv)->SortComparisonFunction->nextArg;
00271 functionReference->nextArg = NULL;
00272 ReturnExpression(theEnv,functionReference);
00273
00274 theMultifield = (struct multifield *) EnvCreateMultifield(theEnv,(unsigned long) argumentSize);
00275
00276 for (i = 0; i < argumentSize; i++)
00277 {
00278 SetMFType(theMultifield,i+1,GetType(theArguments2[i]));
00279 SetMFValue(theMultifield,i+1,GetValue(theArguments2[i]));
00280 }
00281
00282 genfree(theEnv,theArguments2,argumentSize * sizeof(DATA_OBJECT));
00283
00284 SetpType(returnValue,MULTIFIELD);
00285 SetpDOBegin(returnValue,1);
00286 SetpDOEnd(returnValue,argumentSize);
00287 SetpValue(returnValue,(void *) theMultifield);
00288 }
00289
00290
00291
00292
00293
00294
00295 void MergeSort(
00296 void *theEnv,
00297 unsigned long listSize,
00298 DATA_OBJECT *theList,
00299 int (*swapFunction)(void *,DATA_OBJECT *,DATA_OBJECT *))
00300 {
00301 DATA_OBJECT *tempList;
00302 unsigned long middle;
00303
00304 if (listSize <= 1) return;
00305
00306
00307
00308
00309
00310
00311 tempList = (DATA_OBJECT *) genalloc(theEnv,listSize * sizeof(DATA_OBJECT));
00312
00313
00314
00315
00316
00317 middle = (listSize + 1) / 2;
00318 DoMergeSort(theEnv,theList,tempList,0,middle-1,middle,listSize - 1,swapFunction);
00319
00320
00321
00322
00323
00324
00325 genfree(theEnv,tempList,listSize * sizeof(DATA_OBJECT));
00326 }
00327
00328
00329
00330
00331
00332
00333 static void DoMergeSort(
00334 void *theEnv,
00335 DATA_OBJECT *theList,
00336 DATA_OBJECT *tempList,
00337 unsigned long s1,
00338 unsigned long e1,
00339 unsigned long s2,
00340 unsigned long e2,
00341 int (*swapFunction)(void *,DATA_OBJECT *,DATA_OBJECT *))
00342 {
00343 DATA_OBJECT temp;
00344 unsigned long middle, size;
00345 unsigned long c1, c2, mergePoint;
00346
00347
00348
00349 if (s1 == e1)
00350 { }
00351 else if ((s1 + 1) == e1)
00352 {
00353 if ((*swapFunction)(theEnv,&theList[s1],&theList[e1]))
00354 {
00355 TransferDataObjectValues(&temp,&theList[s1]);
00356 TransferDataObjectValues(&theList[s1],&theList[e1]);
00357 TransferDataObjectValues(&theList[e1],&temp);
00358 }
00359 }
00360 else
00361 {
00362 size = ((e1 - s1) + 1);
00363 middle = s1 + ((size + 1) / 2);
00364 DoMergeSort(theEnv,theList,tempList,s1,middle-1,middle,e1,swapFunction);
00365 }
00366
00367 if (s2 == e2)
00368 { }
00369 else if ((s2 + 1) == e2)
00370 {
00371 if ((*swapFunction)(theEnv,&theList[s2],&theList[e2]))
00372 {
00373 TransferDataObjectValues(&temp,&theList[s2]);
00374 TransferDataObjectValues(&theList[s2],&theList[e2]);
00375 TransferDataObjectValues(&theList[e2],&temp);
00376 }
00377 }
00378 else
00379 {
00380 size = ((e2 - s2) + 1);
00381 middle = s2 + ((size + 1) / 2);
00382 DoMergeSort(theEnv,theList,tempList,s2,middle-1,middle,e2,swapFunction);
00383 }
00384
00385
00386
00387
00388
00389 mergePoint = s1;
00390 c1 = s1;
00391 c2 = s2;
00392
00393 while (mergePoint <= e2)
00394 {
00395 if (c1 > e1)
00396 {
00397 TransferDataObjectValues(&tempList[mergePoint],&theList[c2]);
00398 c2++;
00399 mergePoint++;
00400 }
00401 else if (c2 > e2)
00402 {
00403 TransferDataObjectValues(&tempList[mergePoint],&theList[c1]);
00404 c1++;
00405 mergePoint++;
00406 }
00407 else if ((*swapFunction)(theEnv,&theList[c1],&theList[c2]))
00408 {
00409 TransferDataObjectValues(&tempList[mergePoint],&theList[c2]);
00410 c2++;
00411 mergePoint++;
00412 }
00413 else
00414 {
00415 TransferDataObjectValues(&tempList[mergePoint],&theList[c1]);
00416 c1++;
00417 mergePoint++;
00418 }
00419 }
00420
00421
00422
00423
00424
00425 for (c1 = s1; c1 <= e2; c1++)
00426 { TransferDataObjectValues(&theList[c1],&tempList[c1]); }
00427 }
00428
00429
00430