int DaoValue_Compare( DaoValue *left, DaoValue *right ) { double L, R; int res = 0; if( left == right ) return 0; if( left == NULL || right == NULL ) return left < right ? -100 : 100; if( left->type != right->type ){ res = left->type < right->type ? -100 : 100; if( right->type == DAO_TUPLE && right->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left, right->xTuple.items[0] )) <= 0 ) return res; if( (res = DaoValue_Compare( left, right->xTuple.items[1] )) >= 0 ) return res; return 0; }else if( left->type == DAO_TUPLE && left->xTuple.subtype == DAO_PAIR ){ if( (res = DaoValue_Compare( left->xTuple.items[0], right )) >= 0 ) return res; if( (res = DaoValue_Compare( left->xTuple.items[1], right )) <= 0 ) return res; return 0; } #ifdef DAO_WITH_LONGINT if( left->type == DAO_LONG && (right->type && right->type <= DAO_DOUBLE) ){ if( right->type == DAO_INTEGER ){ return DLong_CompareToInteger( left->xLong.value, right->xInteger.value ); } return DLong_CompareToDouble( left->xLong.value, DaoValue_GetDouble( right ) ); }else if( right->type == DAO_LONG && (left->type && left->type <= DAO_DOUBLE) ){ if( left->type == DAO_INTEGER ){ return - DLong_CompareToInteger( right->xLong.value, left->xInteger.value ); } return - DLong_CompareToDouble( right->xLong.value, DaoValue_GetDouble( left ) ); } #endif if( left->type < DAO_INTEGER || left->type > DAO_DOUBLE ) return res; if( right->type < DAO_INTEGER || right->type > DAO_DOUBLE ) return res; L = DaoValue_GetDouble( left ); R = DaoValue_GetDouble( right ); return L == R ? 0 : (L < R ? -1 : 1); } switch( left->type ){ case DAO_NONE : return 0; case DAO_INTEGER : return number_compare( left->xInteger.value, right->xInteger.value ); case DAO_FLOAT : return number_compare( left->xFloat.value, right->xFloat.value ); case DAO_DOUBLE : return number_compare( left->xDouble.value, right->xDouble.value ); case DAO_COMPLEX : return DaoComplex_Compare( & left->xComplex, & right->xComplex ); #ifdef DAO_WITH_LONGINT case DAO_LONG : return DLong_Compare( left->xLong.value, right->xLong.value ); #endif case DAO_STRING : return DString_Compare( left->xString.data, right->xString.data ); case DAO_ENUM : return DaoEnum_Compare( & left->xEnum, & right->xEnum ); case DAO_TUPLE : return DaoTuple_Compare( & left->xTuple, & right->xTuple ); case DAO_LIST : return DaoList_Compare( & left->xList, & right->xList ); case DAO_CDATA : case DAO_CSTRUCT : case DAO_CTYPE : return DaoCstruct_Compare( left, right ); #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : return DaoArray_Compare( & left->xArray, & right->xArray ); #endif } return left < right ? -100 : 100; /* needed for map */ }
void DaoxDataColumn_SetCell( DaoxDataColumn *self, daoint i, DaoValue *value ) { if( value == NULL ){ complex16 zero = {0.0,0.0}; switch( self->type->tid ){ default : GC_DecRC( self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = 0; break; case DAO_FLOAT : self->cells->data.floats[i] = 0.0; break; case DAO_DOUBLE : self->cells->data.doubles[i] = 0.0; break; case DAO_COMPLEX : self->cells->data.complexes[i] = zero; break; case DAO_STRING : DString_Reset( & self->cells->data.strings[i], 0 ); break; } return; } switch( self->type->tid ){ default : GC_ShiftRC( value, self->cells->data.values[i] ); self->cells->data.values[i] = value; break; case DAO_INTEGER : self->cells->data.daoints[i] = DaoValue_GetInteger( value ); break; case DAO_FLOAT : self->cells->data.floats[i] = DaoValue_GetFloat( value ); break; case DAO_DOUBLE : self->cells->data.doubles[i] = DaoValue_GetDouble( value ); break; case DAO_COMPLEX : self->cells->data.complexes[i] = DaoValue_GetComplex( value ); break; case DAO_STRING : DaoValue_GetString( value, & self->cells->data.strings[i] ); break; } }
DLong* DaoValue_GetLong( DaoValue *self, DLong *lng ) { #ifdef DAO_WITH_LONGINT switch( self->type ){ case DAO_INTEGER : DLong_FromInteger( lng, DaoValue_GetInteger( self ) ); break; case DAO_FLOAT : case DAO_DOUBLE : DLong_FromDouble( lng, DaoValue_GetDouble( self ) ); break; case DAO_COMPLEX : DLong_FromDouble( lng, self->xComplex.value.real ); break; case DAO_LONG : DLong_Move( lng, self->xLong.value ); break; case DAO_STRING : DLong_FromString( lng, self->xString.data ); break; default : break; /* TODO list array? */ } #endif return lng; }
static void STD_Array( DaoProcess *proc, DaoValue *p[], int N ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *res, *index = (DaoValue*)(void*)&idint; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoArray *array = DaoProcess_PutArray( proc ); DaoArray *first = NULL; DaoArray *sub = NULL; daoint i, j, k, entry, size = 1; /* if multi-dimensional array is disabled, DaoProcess_PutArray() will raise exception. */ #ifdef DAO_WITH_NUMARRAY for(i=0; i<N; i++){ daoint d = p[i]->xInteger.value; if( d < 0 ){ DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, NULL ); break; } size *= d; } if( size == 0 ) return; if( sect == NULL ) return; // TODO exception if( DaoProcess_PushSectionFrame( proc ) == NULL ) return; entry = proc->topFrame->entry; DaoProcess_AcquireCV( proc ); for(i=0; i<size; i++){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, index ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; res = proc->stackValues[0]; if( i == 0 ){ int D = N; DaoArray_SetDimCount( array, N + (res->type == DAO_ARRAY ? res->xArray.ndim : 0) ); for(j=0; j<N; j++) array->dims[j] = p[j]->xInteger.value; if( res->type == DAO_ARRAY ){ first = DaoArray_Copy( (DaoArray*) res ); if( first->ndim == 2 && (first->dims[0] == 1 || first->dims[1] == 1) ){ D += 1; array->dims[N] = first->dims[ first->dims[0] == 1 ]; }else{ D += first->ndim; memmove( array->dims + N, first->dims, first->ndim*sizeof(daoint) ); } } DaoArray_ResizeArray( array, array->dims, D ); } if( res->type == DAO_ARRAY ){ sub = (DaoArray*) res; if( first == NULL || DaoArray_AlignShape( sub, NULL, first->dims, first->ndim ) ==0 ){ DaoProcess_RaiseException( proc, DAO_ERROR, "inconsistent elements or subarrays" ); break; } k = i * sub->size; for(j=0; j<sub->size; j++){ switch( array->etype ){ case DAO_INTEGER : array->data.i[k+j] = DaoArray_GetInteger( sub, j ); break; case DAO_FLOAT : array->data.f[k+j] = DaoArray_GetFloat( sub, j ); break; case DAO_DOUBLE : array->data.d[k+j] = DaoArray_GetDouble( sub, j ); break; case DAO_COMPLEX : array->data.c[k+j] = DaoArray_GetComplex( sub, j ); break; } } }else{ switch( array->etype ){ case DAO_INTEGER : array->data.i[i] = DaoValue_GetInteger( res ); break; case DAO_FLOAT : array->data.f[i] = DaoValue_GetFloat( res ); break; case DAO_DOUBLE : array->data.d[i] = DaoValue_GetDouble( res ); break; case DAO_COMPLEX : array->data.c[i] = DaoValue_GetComplex( res ); break; } } } DaoProcess_ReleaseCV( proc ); DaoProcess_PopFrame( proc ); if( first ) DaoArray_Delete( first ); #endif }
/* // Assumming the value "self" is compatible to the type "tp", if it is not null. */ DaoValue* DaoValue_SimpleCopyWithTypeX( DaoValue *self, DaoType *tp, DaoDataCache *cache ) { DaoEnum *e; daoint i, n; if( self == NULL ) return dao_none_value; if( (tp == NULL || tp->tid == self->type) && self->type < DAO_ENUM ){ if( cache ){ DaoValue *value = DaoDataCache_MakeValue( cache, self->type ); switch( self->type ){ case DAO_NONE : return self; case DAO_INTEGER : value->xInteger.value = self->xInteger.value; break; case DAO_FLOAT : value->xFloat.value = self->xFloat.value; break; case DAO_DOUBLE : value->xDouble.value = self->xDouble.value; break; case DAO_COMPLEX : value->xComplex.value = self->xComplex.value; break; #ifdef DAO_WITH_LONGINT case DAO_LONG : DLong_Move( value->xLong.value, self->xLong.value ); break; #endif case DAO_STRING : DString_Assign( value->xString.data, self->xString.data ); break; } return value; }else{ switch( self->type ){ case DAO_NONE : return self; case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xInteger.value ); case DAO_FLOAT : return (DaoValue*) DaoFloat_New( self->xFloat.value ); case DAO_DOUBLE : return (DaoValue*) DaoDouble_New( self->xDouble.value ); case DAO_COMPLEX : return (DaoValue*) DaoComplex_New( self->xComplex.value ); case DAO_LONG : return (DaoValue*) DaoLong_Copy( & self->xLong ); case DAO_STRING : return (DaoValue*) DaoString_Copy( & self->xString ); } } return self; /* unreachable; */ }else if( self->type == DAO_ENUM ){ return (DaoValue*) DaoEnum_Copy( & self->xEnum, tp ); }else if( tp && tp->tid >= DAO_INTEGER && tp->tid <= DAO_DOUBLE ){ DaoValue *value = cache ? DaoDataCache_MakeValue( cache, tp->tid ) : NULL; switch( value == NULL ? tp->tid : 0 ){ case DAO_INTEGER : value = (DaoValue*) DaoInteger_New(0); break; case DAO_FLOAT : value = (DaoValue*) DaoFloat_New(0); break; case DAO_DOUBLE : value = (DaoValue*) DaoDouble_New(0); break; } switch( tp->tid ){ case DAO_INTEGER : value->xInteger.value = DaoValue_GetInteger( self ); break; case DAO_FLOAT : value->xFloat.value = DaoValue_GetFloat( self ); break; case DAO_DOUBLE : value->xDouble.value = DaoValue_GetDouble( self ); break; } return value; } #ifdef DAO_WITH_NUMARRAY if( self->type == DAO_ARRAY && self->xArray.original ){ DaoArray_Sliced( (DaoArray*)self ); return self; }else #endif if( self->type == DAO_CSTRUCT || self->type == DAO_CDATA ){ FuncPtrSliced sliced = self->xCstruct.ctype->kernel->Sliced; if( sliced ) (*sliced)( self ); return self; } if( self->xBase.trait & DAO_VALUE_NOCOPY ) return self; if( (self->xBase.trait & DAO_VALUE_CONST) == 0 ) return self; switch( self->type ){ case DAO_LIST : return (DaoValue*) DaoList_Copy( (DaoList*) self, tp ); case DAO_MAP : return (DaoValue*) DaoMap_Copy( (DaoMap*) self, tp ); case DAO_TUPLE : return (DaoValue*) DaoTuple_Copy( (DaoTuple*) self, tp ); #ifdef DAO_WITH_NUMARRAY case DAO_ARRAY : return (DaoValue*) DaoArray_CopyX( (DaoArray*) self, tp ); #endif default : break; } return self; }
float DaoValue_GetFloat( DaoValue *self ) { return (float) DaoValue_GetDouble( self ); }
static void FRAME_PRINT( DaoProcess *proc, DaoValue *p[], int n ) { DaoxDataFrame *self = (DaoxDataFrame*) p[0]; DaoxDataFrame *original = self->original; DaoStream *stream = proc->stdioStream; DaoStream *sstream = DaoStream_New(); DaoValue valueBuffer, *nulls[3] = {NULL,NULL,NULL}; DVector *rlabwidth = DVector_New( sizeof(int) ); DVector *clabwidth = DVector_New( sizeof(int) ); DVector *decimals = DVector_New( sizeof(int) ); DVector *scifmts = DVector_New( sizeof(int) ); DVector *aligns = DVector_New( sizeof(int) ); DString *label = DString_New(1); daoint d, g, i, j, k, s, N, M, K, J = 1; int idwidth, maxwidth = 16, maxdec = 3; char idfmt[16]; char fmt[16]; char buf[512]; sstream->attribs |= DAO_IO_STRING; memset( &valueBuffer, 0, sizeof(DaoValue) ); if( stream == NULL ) stream = proc->vmSpace->stdioStream; if( self->original == NULL ){ DaoxDataFrame_PrepareSlices( self ); DaoDataFrame_MakeSlice( self, proc, nulls, 3, self->slices ); original = self; } N = self->slices->items.pVector[0]->data.daoints[1]; M = self->slices->items.pVector[1]->data.daoints[1]; K = self->slices->items.pVector[2]->data.daoints[1]; DString_Reset( label, 10 + 4*sizeof(void*) + log10(1+N+M+K) ); sprintf( label->mbs, "\nDataFrame[%p]", self ); DaoStream_WriteMBS( stream, label->mbs ); if( original != self ){ sprintf( label->mbs, " (Slices from DataFrame[%p])", original ); DaoStream_WriteMBS( stream, label->mbs ); } sprintf( label->mbs, "\nDimensions: Rows=%" DAO_INT_FORMAT ";", N ); DaoStream_WriteMBS( stream, label->mbs ); sprintf( label->mbs, " Cols=%" DAO_INT_FORMAT ";", M ); DaoStream_WriteMBS( stream, label->mbs ); sprintf( label->mbs, " Deps=%" DAO_INT_FORMAT ";\n", K ); DaoStream_WriteMBS( stream, label->mbs ); idwidth = 1 + (int)log10(N+1); for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); int width = 1 + (int)log10(ii+1); if( width > idwidth ) idwidth = width; } sprintf( idfmt, "%%%i%s:", idwidth, DAO_INT_FORMAT ); if( M == 1 ){ maxwidth = 64; maxdec = 24; }else if( M == 2 ){ maxwidth = 40; maxdec = 12; }else if( M <= 4 ){ maxwidth = 24; maxdec = 6; } for(g=0; g<original->labels[DAOX_DF_ROW]->size; ++g){ int width = 0; for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); DaoxDataFrame_GetLabel( original, DAOX_DF_ROW, g, ii, label ); if( label->size > width ) width = label->size; if( width > maxwidth ) break; } if( width > maxwidth ) width = maxwidth; DVector_PushInt( rlabwidth, width ); } for(j=0; j<M; ++j){ int w, datatype, max = 0, min = 0, dec = 0; daoint width, jj = DaoSlice_GetIndex( self->slices->items.pVector[2], j ); DaoxDataColumn *col = (DaoxDataColumn*) original->columns->items.pVoid[jj]; DVector *cells = col->cells; datatype = DaoType_GetDataType( col->type ); width = DaoxDataColumn_GetPrintWidth( col, 16 ); for(i=0; i<N && i<1000; ++i){ daoint v, ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); complex16 com; switch( datatype ){ case DAO_INTEGER : v = cells->data.daoints[ii]; w = log10( fabs(v) + 1E-32 ) + (v < 0); if( w > max ) max = w; break; case DAO_FLOAT : CheckPrintWidth( cells->data.floats[ii], & max, & min, & dec ); break; case DAO_DOUBLE : CheckPrintWidth( cells->data.doubles[ii], & max, & min, & dec ); break; case DAO_COMPLEX : com = cells->data.complexes[ii]; CheckPrintWidth( com.real, & max, & min, & dec ); CheckPrintWidth( com.imag, & max, & min, & dec ); break; case DAO_STRING : if( cells->data.strings[i].size > max ) max = cells->data.strings[i].size; break; default : break; } } if( dec > maxdec ) dec = maxdec; if( col->type->tid == DAO_COMPLEX ){ max *= 2; min *= 2; } if( datatype == 0 ){ width = maxwidth; DVector_PushInt( aligns, 1 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, 0 ); }else if( datatype == DAO_STRING ){ width = max; DVector_PushInt( aligns, 1 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, 0 ); }else if( max >= maxwidth || min <= -dec ){ width = 16; DVector_PushInt( aligns, 0 ); DVector_PushInt( scifmts, 1 ); DVector_PushInt( decimals, dec ); }else{ width = max + dec + 1; if( col->type->tid == DAO_COMPLEX ) width += dec + 6; DVector_PushInt( aligns, 0 ); DVector_PushInt( scifmts, 0 ); DVector_PushInt( decimals, dec ); } for(g=0; g<original->labels[DAOX_DF_COL]->size; ++g){ DaoxDataFrame_GetLabel( original, DAOX_DF_COL, g, jj, label ); if( label->size > width ) width = label->size; if( width > maxwidth ) break; } if( width > maxwidth ) width = maxwidth; DVector_PushInt( clabwidth, width ); } for(k=0; k<K; ++k){ daoint kk = DaoSlice_GetIndex( self->slices->items.pVector[2], k ); DaoStream_WriteMBS( stream, "Depth: " ); DaoStream_WriteInt( stream, kk ); DaoStream_WriteMBS( stream, ";" ); if( original->labels[DAOX_DF_DEP]->size ) DaoStream_WriteMBS( stream, "\nLabels:" ); for(g=0; g<original->labels[DAOX_DF_DEP]->size; ++g){ DaoxDataFrame_GetLabel( original, DAOX_DF_DEP, g, kk, label ); DaoStream_WriteMBS( stream, " " ); DaoStream_WriteString( stream, label ); DaoStream_WriteMBS( stream, ";" ); } DaoStream_WriteMBS( stream, "\n" ); for(j=0; j<M; j=J){ int width2, width = idwidth+1; for(i=0; i<rlabwidth->size; ++i) width += rlabwidth->data.ints[i] + 1; width += 1; J = j; width2 = width; for(J=j; J<M; ++J){ daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[1], J ); width2 += clabwidth->data.ints[J] + 2; if( width2 > 80 ){ width2 -= clabwidth->data.ints[J] + 2; break; } } if( J == j ) J += 1; sprintf( buf, "from %" DAO_INT_FORMAT " to %" DAO_INT_FORMAT ":\n", j, J-1 ); DaoStream_WriteMBS( stream, j == 0 ? "| Columns " : "> Columns " ); DaoStream_WriteMBS( stream, buf ); for(g=0; g<original->labels[DAOX_DF_COL]->size; ++g){ sprintf( fmt, "%%-%is", width ); sprintf( buf, fmt, j == 0 ? "|" : ">" ); DaoStream_WriteMBS( stream, buf ); for(s=j; s<J; ++s){ daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[1], s ); int width = clabwidth->data.ints[s]; int align = aligns->data.ints[s]; if( align ){ sprintf( fmt, "%%-%is", width ); }else{ sprintf( fmt, "%%%is", width ); } DaoxDataFrame_GetLabel( original, DAOX_DF_COL, g, jj, label ); if( label->size > width ) DString_Reset( label, width ); snprintf( buf, width+1, fmt, label->mbs ); DaoStream_WriteMBS( stream, " " ); DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, "\n" ); } printf( j == 0 ? "|" : ">" ); while( --width2 ) printf( "-" ); DaoStream_WriteMBS( stream, J < M ? ">" : "|" ); DaoStream_WriteMBS( stream, "\n" ); for(i=0; i<N; ++i){ daoint ii = DaoSlice_GetIndex( self->slices->items.pVector[0], i ); sprintf( buf, idfmt, ii ); DaoStream_WriteMBS( stream, buf ); for(g=0; g<original->labels[DAOX_DF_ROW]->size; ++g){ int width = rlabwidth->data.ints[g]; DaoxDataFrame_GetLabel( original, DAOX_DF_ROW, g, ii, label ); if( label->size > width ) DString_Reset( label, width ); if( g ) DaoStream_WriteMBS( stream, "," ); sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, label->mbs ); DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, ": " ); for(s=j; s<J; ++s){ int scifmt = scifmts->data.ints[s]; int dec = decimals->data.ints[s]; int width = clabwidth->data.ints[s]; daoint jj = DaoSlice_GetIndex( self->slices->items.pVector[2], s ); DaoxDataColumn *col = (DaoxDataColumn*) original->columns->items.pVoid[jj]; DaoValue *value = DaoxDataColumn_GetCell( col, i, & valueBuffer ); DaoStream_WriteMBS( stream, " " ); if( value == NULL ){ sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, " " ); }else if( value->type == DAO_INTEGER ){ sprintf( fmt, "%%%i%s", width, DAO_INT_FORMAT ); snprintf( buf, width+1, fmt, value->xInteger.value ); }else if( value->type == DAO_FLOAT || value->type == DAO_DOUBLE ){ double f = DaoValue_GetDouble( value ); if( scifmt ){ sprintf( fmt, "%%%iE", width ); }else{ sprintf( fmt, "%%%i.%if", width, dec ); } snprintf( buf, width+1, fmt, f ); }else if( value->type == DAO_COMPLEX ){ complex16 com = value->xComplex.value; char s = com.imag>=0 ? '+' : '-'; int w = width/2-2; int d = dec; if( scifmt ){ sprintf( fmt, "(%%%i.3E,%%%i.3E)", w, w ); }else{ sprintf( fmt, "(%%%i.%if,%%%i.%if)", w, d, w, d ); } snprintf( buf, width, fmt, com.real, com.imag ); }else{ DString_Reset( sstream->streamString, 0 ); DaoValue_Print( value, proc, sstream, NULL ); DString_Reset( label, 0 ); DString_Append( label, sstream->streamString ); if( label->size > width ) DString_Reset( label, width ); DString_ChangeMBS( label, "%t", "\\t", 0 ); DString_ChangeMBS( label, "%n", "\\n", 0 ); sprintf( fmt, "%%-%is", width ); snprintf( buf, width+1, fmt, label->mbs ); } DaoStream_WriteMBS( stream, buf ); } DaoStream_WriteMBS( stream, "\n" ); } DaoStream_WriteMBS( stream, "\n" ); } } DaoStream_Delete( sstream ); DVector_Delete( aligns ); DVector_Delete( scifmts ); DVector_Delete( decimals ); DVector_Delete( rlabwidth ); DVector_Delete( clabwidth ); DString_Delete( label ); }