📄 value.cc
字号:
\ delete index; \ delete index_is_copy; \ delete cur; \ }#define SUBOP_ABORT(length,retval) \ SUBOP_CLEANUP_2(length) \ delete len; \ return retval; if ( ! IsNumeric() && VecRefDeref()->Type() != TYPE_STRING ) { error->Report( "invalid type in n-D array operation:", this ); return error_value(); } // Collect attributes. int args_len = args_val->length(); const attributeptr ptr = AttributePtr(); const Value* shape_val = ptr ? (*ptr)["shape"] : 0; if ( ! shape_val || ! shape_val->IsNumeric() ) { warn->Report( "invalid or non-existant \"shape\" attribute" ); if ( args_len >= 1 ) return operator[]( (*args_val)[0] ); else return copy_value( this ); } int shape_len = shape_val->Length(); if ( shape_len != args_len ) { error->Report( "invalid number of indexes for:", this ); return error_value(); } int shape_is_copy; int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len ); Value* op_val = (*ptr)["op[]"]; int* factor = new int[shape_len]; int cur_factor = 1; int offset = 0; int max_len = 0; for ( int i = 0; i < args_len; ++i ) { const Value* arg = (*args_val)[i]; if ( arg ) { if ( ! arg->IsNumeric() ) { error->Report( "index #", i+1, "into", this, "is not numeric"); SUBOP_CLEANUP_1 return error_value(); } if ( arg->length > max_len ) max_len = arg->length; if ( max_len == 1 ) { int ind = arg->IntVal(); if ( ind < 1 || ind > shape[i] ) { error->Report( "index #", i+1, "into", this, "is out of range"); SUBOP_CLEANUP_1 return error_value(); } offset += cur_factor * (ind - 1); } } else { // Missing subscript. if ( shape[i] > max_len ) max_len = shape[i]; if ( max_len == 1 ) offset += cur_factor * (shape[i] - 1); } factor[i] = cur_factor; cur_factor *= shape[i]; } // Check to see if we're valid. if ( cur_factor > Length() ) { error->Report( "\"::shape\"/length mismatch" ); SUBOP_CLEANUP_1 return error_value(); } if ( max_len == 1 ) { SUBOP_CLEANUP_1 ++offset; // Should separate ArrayRef to get a single value?? return ArrayRef( &offset, 1 ); } int* index_is_copy = new int[shape_len]; int** index = new int*[shape_len]; int* cur = new int[shape_len]; int* len = new int[shape_len]; int vecsize = 1; int is_element = 1; int spoof_dimension = 0; for ( i = 0; i < args_len; ++i ) { const Value* arg = (*args_val)[i]; if ( arg ) { index[i] = GenerateIndices( arg, len[i], index_is_copy[i], 0 ); spoof_dimension = 0; } else { // Spoof entire dimension. len[i] = shape[i]; index[i] = new int[len[i]]; for ( int j = 0; j < len[i]; j++ ) index[i][j] = j+1; index_is_copy[i] = 1; spoof_dimension = 1; } if ( is_element && len[i] > 1 ) is_element = 0; vecsize *= len[i]; cur[i] = 0; if ( ! spoof_dimension ) { for ( int j = 0; j < len[i]; ++j ) { if ( index[i][j] >= 1 && index[i][j] <= shape[i] ) continue; if ( len[i] > 1 ) error->Report( "index #", i+1, ",", j+1, " into ", this, "is out of range."); else error->Report( "index #", i+1, "into", this, "is out of range."); SUBOP_ABORT(i, error_value()) } } } // Loop through filling resultant vector. Value* result; switch ( Type() ) {#define SUBSCRIPT_OP_ACTION(tag,type,accessor,LEN,OFFSET,copy_func,ERROR)\ case tag: \ { \ type* vec = accessor; \ type* ret = new type[vecsize]; \ \ for ( int v = 0; v < vecsize; ++v ) \ { \ /**** Calculate offset ****/ \ for ( i = 0, offset = 0; i < shape_len; ++i ) \ offset += factor[i] * \ (index[i][cur[i]]-1); \ /**** Set Value ****/ \ ERROR \ ret[v] = copy_func( vec[OFFSET] ); \ /**** Advance counters ****/ \ for ( i = 0; i < shape_len; ++i ) \ if ( ++cur[i] < len[i] ) \ break; \ else \ cur[i] = 0; \ } \ \ result = new Value( ret, vecsize ); \ if ( ! is_element ) \ { \ for ( int x = 0, z = 0; x < shape_len; ++x ) \ if ( len[x] > 1 ) \ len[z++] = len[x]; \ \ result->AssignAttribute( "shape", \ new Value( len, z ) ); \ if ( op_val ) \ result->AssignAttribute( "op[]", op_val );\ } \ else \ delete len; \ } \ break;SUBSCRIPT_OP_ACTION(TYPE_BOOL,glish_bool,BoolPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_BYTE,byte,BytePtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_SHORT,short,ShortPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_INT,int,IntPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_FLOAT,float,FloatPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_DOUBLE,double,DoublePtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_COMPLEX,complex,ComplexPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_DCOMPLEX,dcomplex,DcomplexPtr(),length,offset,,)SUBSCRIPT_OP_ACTION(TYPE_STRING,charptr,StringPtr(),length,offset,strdup,) case TYPE_SUBVEC_REF: case TYPE_SUBVEC_CONST: { VecRef* ref = VecRefPtr(); Value* theVal = ref->Val(); int theLen = theVal->Length(); switch ( theVal->Type() ) {#define SUBSCRIPT_OP_ACTION_XLATE(EXTRA_ERROR) \ int err; \ int off = ref->TranslateIndex( offset, &err ); \ if ( err ) \ { \ EXTRA_ERROR \ delete ret; \ SUBOP_CLEANUP_2(shape_len) \ return error_value(); \ }SUBSCRIPT_OP_ACTION(TYPE_BOOL, glish_bool, theVal->BoolPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_BYTE, byte, theVal->BytePtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_SHORT, short, theVal->ShortPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_INT, int, theVal->IntPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_FLOAT, float, theVal->FloatPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_DOUBLE, double, theVal->DoublePtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_COMPLEX, complex, theVal->ComplexPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_DCOMPLEX, dcomplex, theVal->DcomplexPtr(), theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))SUBSCRIPT_OP_ACTION(TYPE_STRING, charptr, theVal->StringPtr(), theLen, off,strdup,SUBSCRIPT_OP_ACTION_XLATE(for(int X=0;X<v;X++) delete (char *) ret[X];)) default: fatal->Report( "bad subref type in Value::operator[]" ); } } break; default: fatal->Report( "bad type in Value::operator[]" ); } SUBOP_CLEANUP_2(shape_len) return result; }Value* Value::Pick( const Value *index ) const {#define PICK_CLEANUP \ if ( shape_is_copy ) \ delete shape; \ if ( ishape_is_copy ) \ delete ishape; \ if ( indx_is_copy ) \ delete indx; \ delete factor;#define PICK_INITIALIZE(error_return,SHORT) \ const attributeptr attr = AttributePtr(); \ const attributeptr iattr = index->AttributePtr(); \ const Value* shape_val = 0; \ const Value* ishape_val = 0; \ int shape_len = 0; \ int ishape_len = 0; \ \ if ( attr && (shape_val = (*attr)["shape"]) && \ shape_val->IsNumeric() ) \ shape_len = shape_val->Length(); \ if ( iattr && (ishape_val = (*iattr)["shape"]) && \ ishape_val->IsNumeric() ) \ ishape_len = ishape_val->Length(); \ \ /* Neither has a shape so pick from the vector. */ \ if ( ishape_len <= 1 && shape_len <= 1 ) \ { \ SHORT \ } \ \ if ( ! ishape_len ) \ { \ if ( ishape_val ) \ error->Report("error in the array \"::shape\": ",\ ishape_val ); \ else \ error->Report( "no \"::shape\" for ", index, \ " but the array has \"::shape\"" ); \ return error_return; \ } \ if ( ! shape_len ) \ { \ if ( shape_val ) \ error->Report("error in the array \"::shape\": ",\ shape_val ); \ else \ error->Report( "no \"::shape\" for ", this, \ " but the index has \"::shape\"" ); \ return error_return; \ } \ \ if ( ishape_len > 2 ) \ { \ error->Report("invalid index of dimension (=", ishape_len, \ ") greater than 2"); \ return error_return; \ } \ \ int shape_is_copy = 0; \ int ishape_is_copy = 0; \ int indx_is_copy = 0; \ int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len );\ int* ishape = \ ishape_val->CoerceToIntArray( ishape_is_copy, ishape_len );\ int ilen = index->Length(); \ int len = Length(); \ int* factor = new int[shape_len]; \ int offset = 1; \ int* indx = index->CoerceToIntArray( indx_is_copy, ilen ); \ Value* result = 0; \ \ if ( ishape[1] != shape_len ) \ { \ PICK_CLEANUP \ error->Report( "wrong number of columns in index (=", \ ishape[1], ") expected ", shape_len ); \ return error_return; \ } \ if ( ilen < ishape[0] * ishape[1] ) \ { \ PICK_CLEANUP \ error->Report( "Index \"::shape\"/length mismatch" );\ return error_return; \ } \ for ( int i = 0; i < shape_len; ++i ) \ { \ factor[i] = offset; \ offset *= shape[i]; \ } \ \ if ( len < offset ) \ { \ PICK_CLEANUP \ error->Report("Array \"::shape\"/length mismatch"); \ return error_return; \ } PICK_INITIALIZE(error_value(),return this->operator[]( index );) switch ( Type() ) {#define PICK_ACTION_CLEANUP for(int X=0;X<i;X++) delete (char *) ret[X];#define PICK_ACTION(tag,type,accessor,OFFSET,COPY_FUNC,XLATE,CLEANUP) \ case tag: \ { \ type* ptr = accessor(); \ type* ret = new type[ishape[0]]; \ int cur = 0; \ for ( i = 0; i < ishape[0]; ++i ) \ { \ for ( int j = 0, offset = 0; j < ishape[1]; ++j )\ { \ cur = indx[i + j * ishape[0]]; \ if ( cur < 1 || cur > shape[j] ) \ { \ PICK_CLEANUP \ CLEANUP \ delete ret; \ error->Report( "index number ", j,\ " (=", cur, ") is out of range" );\ return error_value(); \ } \ offset += factor[j] * (cur-1); \ } \ XLATE \ ret[i] = COPY_FUNC( ptr[ OFFSET ] ); \ } \ result = new Value( ret, ishape[0] ); \ } \ break; PICK_ACTION(TYPE_BOOL,glish_bool,BoolPtr,offset,,,) PICK_ACTION(TYPE_BYTE,byte,BytePtr,offset,,,) PICK_ACTION(TYPE_SHORT,short,ShortPtr,offset,,,) PICK_ACTION(TYPE_INT,int,IntPtr,offset,,,) PICK_ACTION(TYPE_FLOAT,float,FloatPtr,offset,,,) PICK_ACTION(TYPE_DOUBLE,double,DoublePtr,offset,,,) PICK_ACTION(TYPE_COMPLEX,complex,ComplexPtr,offset,,,) PICK_ACTION(TYPE_DCOMPLEX,dcomplex,DcomplexPtr,offset,,,) PICK_ACTION(TYPE_STRING,charptr,StringPtr,offset,strdup,, PICK_ACTION_CLEANUP) case TYPE_SUBVEC_REF: case TYPE_SUBVEC_CONST: { VecRef* ref = VecRefPtr(); Value* theVal = ref->Val(); int theLen = theVal->Length(); switch ( theVal->Type() ) {#define PICK_ACTION_XLATE(CLEANUP) \ int err; \ int off = ref->TranslateIndex( offset, &err ); \ if ( err ) \ { \ CLEANUP \ delete ret; \ error->Report( "index number ", j, " (=",cur, \ ") is out of range. Sub-vector reference may be invalid" );\ return error_value(); \ }PICK_ACTION(TYPE_BOOL,glish_bool,theVal->BoolPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_BYTE,byte,theVal->BytePtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_SHORT,short,theVal->ShortPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_INT,int,theVal->IntPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_FLOAT,float,theVal->FloatPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_DOUBLE,double,theVal->DoublePtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_COMPLEX,complex,theVal->ComplexPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_DCOMPLEX,dcomplex,theVal->DcomplexPtr,off,,PICK_ACTION_XLATE(;),)PICK_ACTION(TYPE_STRING,charptr,theVal->StringPtr,off,strdup, PICK_ACTION_XLATE(PICK_ACTION_CLEANUP),PICK_ACTION_CLEANUP) default: fatal->Report( "bad subref type in Value::Pick" ); } } break; default: fatal->Report( "bad subref type in Value::Pick" ); } PICK_CLEANUP return result; }Value* Value::PickRef( const Value *index ) { if ( ! IsNumeric() && Type() != TYPE_STRING ) { error->Report( "non-numeric type in subreference operation:", this ); return error_value(); } PICK_INITIALIZE(error_value(),return this->operator[]( index );) int* ret = new int[ishape[0]]; int cur = 0; for ( i = 0; i < ishape[0]; ++i ) { for ( int j = 0, offset = 0; j < ishape[1]; ++j ) { cur = indx[i + j * ishape[0]]; if ( cur < 1 || cur > shape[j] ) { PICK_CLEANUP delete ret; error->Report( "index number ", j, " (=",cur, ") is out of range" ); return error_value(); } offset += factor[j] * (cur-1); } ret[i] = offset + 1; } result = new Value((Value*)this,ret,ishape[0],VAL_REF); const attributeptr cap = result->AttributePtr(); if ( (*cap)["shape"] ) { if ( cap->Length() == 1 ) result->DeleteAttributes(); else { attributeptr ap = result->ModAttributePtr(); delete ap->Remove( "shape" ); } } PICK_CLEANUP return result; }void Value::PickAssign( const Value* index, Value* value ) {#define PICKASSIGN_SHORT \ AssignElements( index, value ); \ return; PICK_INITIALIZE(,PICKASSIGN_SHORT) switch ( Type() ) {#define PICKASSIGN_ACTION(tag,type,to_accessor,from_accessor,COPY_FUNC,XLATE)\ case tag: \ { \ int cur = 0; \ int* offset_vec = new int[ishape[0]]; \ for ( i = 0; i < ishape[0]; ++i ) \ { \ offset_vec[i] = 0; \ for ( int j = 0; j < ishape[1]; ++j ) \ { \ cur = indx[i + j * ishape[0]]; \ if ( cur < 1 || cur > shape[j] ) \ { \ PICK_CLEANUP \ delete offset_vec; \ error->Report("index number ", i,\ " (=", cur, \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -