TAC* fun_def_tac(linkedList_t* node, TAC* header, TAC* local_defs, TAC* block) { linkedList_t* start_label = function_start_label(node); linkedList_t* end_label = function_end_label(node); return append( append( append( append( append( append( append( tac(TAC_JUMP,end_label,NULL,NULL), tac(TAC_LABEL,start_label,NULL,NULL) ), tac(TAC_BEGINFUN, node, NULL, NULL) ), header ), local_defs ), block ), tac(TAC_ENDFUN, node, NULL, NULL) ), tac(TAC_LABEL,end_label,NULL,NULL) ); }
int main(int argc, char *argv[]) { char dst[100]; char *str1 = "hi,\nI am Lilei,\nHow are you."; tac(str1, dst); fprintf(stdout, "%s", dst); fprintf(stdout, "\n\n"); char *str2 = "h."; tac(str2, dst); fprintf(stdout, "%s", dst); fprintf(stdout, "\n\n"); char *str3 ="h"; tac(str3, dst); fprintf(stdout, "%s", dst); fprintf(stdout, "\n\n"); char *str4 ="hello\nworld\n"; tac(str4, dst); fprintf(stdout, "%s", dst); return 0; }
TAC* loop_tac(TAC* test, TAC* loopBlock) { linkedList_t* testResult = test->destination; linkedList_t* loopLabel = newLabel(); linkedList_t* endLabel = newLabel(); TAC* new_test = clone(test); return append( append( append( append( test, append( tac(TAC_LABEL, loopLabel, NULL, NULL), tac(TAC_IFZ, endLabel, testResult, NULL) ) ), loopBlock ), append( new_test, tac(TAC_JUMP, loopLabel, NULL, NULL) ) ), tac(TAC_LABEL, endLabel, NULL, NULL) ); }
TAC* ifZero_tac(TAC* test, TAC* thenBlock, TAC* elseBlock) { TAC* result; linkedList_t* testResult = test->destination; linkedList_t* elseLabel = newLabel(); TAC* ifThen = append(append(test, tac(TAC_IFZ, elseLabel, testResult, NULL)), thenBlock); if(elseBlock == NULL) { result = append(ifThen, tac(TAC_LABEL, elseLabel, NULL, NULL)); } else { linkedList_t* endLabel = newLabel(); result = append( append( append( append( ifThen, tac(TAC_JUMP, endLabel, NULL, NULL) ), tac(TAC_LABEL, elseLabel, NULL, NULL) ), elseBlock ), tac(TAC_LABEL, endLabel, NULL, NULL) ); } return result; }
TAC* assignment_tac(TAC* variable, TAC* expression) { switch(variable->tac_type) { case TAC_SYMBOL: return append(expression, tac(TAC_MOVE, variable->destination, expression->destination, NULL)); break; case TAC_ARRAYACCESS: return append(expression, tac(TAC_ARRAYASSIGN, variable->destination, variable->source1, expression->destination)); break; //case TAC_DEREF: return append(expression, append(variable, tac(TAC_MOVE_I, variable->destination, expression->destination, NULL))); break; } }
TAC* binaryOp_tac(tacType_t type, TAC** children) { linkedList_t* temp1 = children[0]->destination; linkedList_t* temp2 = children[1]->destination; return append(append(children[0], children[1]), tac(type, newTemp(), temp1, temp2)); }
double toc() { tac(); double t = total; total = 0; return t; }
TAC* args_tac(TAC** children) { if(children[0] == NULL) // A função não recebe argumentos return NULL; if(children[1] == NULL) // Último argumento (calculado em children[0]) { return append(children[0], tac(TAC_ARG, NULL, children[0]->destination, NULL)); } else // Mais de um argumento, argumentos anteriores empilhados em children[0] e último argumento calculado em children[1] { return append(children[0], append(children[1], tac(TAC_ARG, NULL, children[1]->destination, NULL))); } }
TAC* get_args_tac(TAC** children) { if(children[0] == NULL && children[1] == NULL) // A função não recebe argumentos return NULL; if(children[2] == NULL) // Último parâmetro (calculado em children[1]) { return append(children[1], tac(TAC_GET_ARG, children[1]->destination, NULL, NULL)); } else // Mais de um parâmetro, parâmetros anteriores desempilhados em children[0] e último parâmetro calculado em children[2] { return append(tac(TAC_GET_ARG, children[2]->destination, NULL, NULL), append(children[0], children[2])); } }
TAC* array_declaration_tac(TAC* id, AST* literal_list) { if(literal_list == NULL) return NULL; if(literal_list->child[0] != NULL) { if(literal_list->child[0]->child[1] == NULL) return NULL; return append(array_declaration_tac(id,literal_list->child[0]), tac(TAC_ARRAYASSIGN, id->destination, literal_list->child[0]->child[1]->node, NULL)); } else { return append(array_declaration_tac(id,literal_list->child[0]), tac(TAC_ARRAYASSIGN, id->destination, literal_list->child[1]->node, NULL)); } }
int main(int argc, char *argv[]) { const int logN = 10; const int ITER = 10000; struct fftw_state fftw; struct epiphany_state epi; // FFTW fftw_init(&fftw, logN); tic(); fftw_run(&fftw, ITER); tac("fftw ", logN, ITER); // Epiphany epiphany_init(&epi, logN); // C variant tic(); epiphany_run(&epi, ITER, 0); tac("epiphany C ", logN, ITER); compare( fftw_get_result(&fftw), epiphany_get_result(&epi), logN ); // Assembly variant tic(); epiphany_run(&epi, ITER, 1); tac("epiphany ASM ", logN, ITER); compare( fftw_get_result(&fftw), epiphany_get_result(&epi), logN ); epiphany_fini(&epi); fftw_fini(&fftw); return 0; }
void IntermediateCode::threeAddressCode(std::string pLabel) { if(applyLabel) { ThreeAddressCode tac(TAC_NO_OP); addTAC( tac ); } label = pLabel; applyLabel = true; }
TAC* clone(TAC* original) { TAC* tac_clone = tac(original->tac_type, original->destination, original->source1, original->source2); TAC* clone_ptr = tac_clone->prev; TAC* original_ptr = original->prev; while(original_ptr != NULL) { clone_ptr = tac(original_ptr->tac_type, original_ptr->destination, original_ptr->source1, original_ptr->source2); clone_ptr->prev = original_ptr->prev; original_ptr = original_ptr->prev; clone_ptr = clone_ptr->prev; } return tac_clone; }
int main(int argc, char *argv[]) { int c; static struct option const long_options[] = { {"help", 0, NULL, 'h'}, {NULL, 0, NULL, 0} }; program_name = argv[0]; atexit(tac_exit); while((c = getopt_long(argc, argv, "h", long_options, NULL)) != -1) { switch(c) { case 'h': usage_exit(EXIT_SUCESS); break; default: usage_exit(EXIT_FAILURE); break; } } if(optind < argc) /*这些文件是要tac的文件列表*/ { while(optind < argc) tac(argv[optind++]); } else { usage_exit(EXIT_FAILURE); } exit_status = EXIT_SUCESS; exit(exit_status); }
void IntermediateCode::threeAddressCode(attr destAddr, OpCode opCode, attr operand) { ThreeAddressCode tac(destAddr, operand, opCode); addTAC( tac ); }
void IntermediateCode::threeAddressCode(OpCode opCode, attr paramAddr) { ThreeAddressCode tac(paramAddr, opCode); addTAC( tac ); }
void IntermediateCode::threeAddressCode(attr destAddr, OpCode opCode, attr param1, attr param2) { ThreeAddressCode tac(destAddr, param1, param2, opCode); addTAC( tac ); }
void IntermediateCode::threeAddressCode(attr destAddr, OpCode opCode, std::string label, int paramCount) { ThreeAddressCode tac(destAddr, label, paramCount, opCode); addTAC( tac ); }
void IntermediateCode::threeAddressCode(OpCode opCode, std::string label) { ThreeAddressCode tac(label, opCode); addTAC( tac ); }
void IntermediateCode::threeAddressCode(OpCode opCode, attr operand, std::string gotoLabel) { ThreeAddressCode tac( operand, gotoLabel, opCode ); addTAC( tac ); }
void IntermediateCode::threeAddressCode(int rawAddress, OpCode opCode, std::string callLabel, int paramCount) { attr ra; ra.addr = rawAddress; ThreeAddressCode tac(ra, callLabel, paramCount, opCode); addTAC( tac ); }
TAC* pointer_declaration_tac(TAC* id, TAC* literal) { linkedList_t* temp = newTemp(); return tac(TAC_MOVE_I,temp,literal->destination,NULL); }
void IntermediateCode::threeAddressCode(OpCode opCode) { ThreeAddressCode tac(opCode); addTAC( tac ); }
TAC* call_tac(TAC* funcId, TAC* args) { return append(append(args, funcId), tac(TAC_CALL, newTemp(), funcId->destination, NULL)); }
TAC* output_tac(TAC* elements) { return append(elements, tac(TAC_PRINT,NULL,NULL,NULL)); }
TAC* return_tac(TAC* expr) { return append(expr, tac(TAC_RET, NULL, expr->destination, NULL)); }
void IntermediateCode::threeAddressCode(attr result, OpCode opCode, int index) { ThreeAddressCode tac(result, index, opCode); addTAC( tac ); }
TAC* declaration_tac(TAC* id, TAC* literal) { return tac(TAC_MOVE, id->destination, literal->destination, NULL); }
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ ALLOCATES(); CreateTicTacToc( CallMatlab ); CreateTicTacToc( callSort ); int I, J, K, ii, jj, kk; int IJ, IJK, IJK_1; int DI, DJ, DK, DIJK, DIJK_1; int CDI, CDJ, CDK; int result, fevals = 0; int NVOLS, NVOLS_1, n, s, s_start, s_end, v_init; real *volumes, *V, x, y, *DIST, *order, last_distance; int *VV=NULL, nV, v, vv; char skip; triplet *TS=NULL, *DTS=NULL, T; mxArray *INPUT[2]={NULL,NULL}, *OUTPUT[3]={NULL,NULL,NULL}; double *MAXs, LAST_MAX; double thisMINx, thisMINy; double *idxs; double *vols; double *ijk; char callSort; mwSize toVec[2]={1,1}; char VERBOSE = 0; char STR[1024]; if( nlhs > 1 ){ mxErrMsgTxt("too much outputs"); } if( mxIsChar( prhs[nrhs-1] ) ){ mxGetString( prhs[nrhs-1], STR, 100 ); if( ! myStrcmpi(STR,"verbose") ){ VERBOSE = 1; } else { mxErrMsgTxt("only 'verbose' option allowed."); } nrhs = nrhs-1; } if( nrhs != 3 ){ mxErrMsgTxt("sintax error. max_min_multiples_erodes( V , F , volumes )"); } if( mxGetClassID( prhs[1] ) != mxFUNCTION_CLASS ){ mxErrMsgTxt("F have to be a function_handle."); } if( myNDims( prhs[0] ) > 3 ){ mxErrMsgTxt("bigger than 3d arrays is not allowed."); } NVOLS = myNumel( prhs[2] ); NVOLS_1 = NVOLS - 1; volumes = myGetPr( prhs[2] ); I = mySize( prhs[0] , 0 ); J = mySize( prhs[0] , 1 ); K = mySize( prhs[0] , 2 ); IJ = I*J; IJK = IJ*K; VV = (int *) mxMalloc( IJK*sizeof( int ) ); TS = (triplet *) mxMalloc( IJK*sizeof( triplet ) ); V = myGetPr( prhs[0] ); v = 0; nV = 0; for( kk = 0 ; kk < K ; kk++ ){ for( jj = 0 ; jj < J ; jj++ ){ for( ii = 0 ; ii < I ; ii++ ){ x = V[ v ]; if( x == x ){ VV[ nV ] = v; TS[ v ].isnan = 0; TS[ v ].i = ii; TS[ v ].j = jj; TS[ v ].k = kk; nV++; } else { TS[ v ].isnan = 1; } v++; }}} INPUT[0] = prhs[1]; INPUT[1] = mxCreateNumericMatrix( 1 , 3 , mxDOUBLE_CLASS , mxREAL ); ijk = (double *) mxGetData( INPUT[1] ); ijk[0] = TS[ VV[ nV/2] ].i + 1; ijk[1] = TS[ VV[ nV/2] ].j + 1; ijk[2] = TS[ VV[ nV/2] ].k + 1; OUTPUT[2] = mexCallMATLABWithTrap( 2 , OUTPUT , 2 , INPUT , "feval" ); if( OUTPUT[2] == NULL ){ callSort = 0; if( mxGetClassID( OUTPUT[0] ) != mxDOUBLE_CLASS ){ if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1]=NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } mxErrMsgTxt("F debe retornar un double en el primer output."); } if( mxGetClassID( OUTPUT[1] ) != mxDOUBLE_CLASS ){ if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1]=NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } mxErrMsgTxt("F debe retornar un double en el segundo output."); } } else { callSort = 1; if( VERBOSE ){ mexPrintf("sort has to be called\n"); } mxDestroyArray( OUTPUT[2] ); OUTPUT[2] = NULL; result = mexCallMATLAB( 1 , OUTPUT , 2 , INPUT , "feval" ); if( result ){ mxErrMsgTxt("error computing la funcion."); } if( mxGetClassID( OUTPUT[0] ) != mxDOUBLE_CLASS ){ if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1]=NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } mxErrMsgTxt("F debe retornar un double en el primer output."); } } DI = mySize( OUTPUT[0] , 0 ); DJ = mySize( OUTPUT[0] , 1 ); DK = mySize( OUTPUT[0] , 2 ); DTS = (triplet *) mxMalloc( 2*DI*DJ*DK*sizeof( triplet ) ); plhs[0] = mxCreateNumericMatrix( NVOLS , 1 , mxREAL_CLASS , mxREAL ); MAXs = (real *) mxGetData( plhs[0] ); for( n = 0 ; n < NVOLS ; n++ ){ MAXs[n] = -10000; } LAST_MAX = MAXs[ NVOLS_1 ]; for( v_init = 0 ; v_init < EVERY ; v_init++ ){ if( utIsInterruptPending() ){ if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1]=NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } mexPrintf("USER INTERRUP!!!\n"); mxErrMsgTxt("USER INTERRUP!!!"); } if( VERBOSE ){ mexPrintf("v_init: %d (%g) of %d\n", v_init , LAST_MAX , EVERY ); } for( v = v_init ; v < nV ; v += EVERY ){ vv = VV[ v ]; thisMINx = V[ vv ]; thisMINy = -thisMINx; if( ( thisMINx < LAST_MAX ) && ( thisMINy < LAST_MAX ) ){ continue; } T = TS[ vv ]; ijk[0] = T.i + 1; ijk[1] = T.j + 1; ijk[2] = T.k + 1; if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } if( !callSort ){ tic( CallMatlab ); result = mexCallMATLAB( 2 , OUTPUT , 2 , INPUT , "feval" ); fevals++; tac( CallMatlab ); } else { tic( CallMatlab ); result = mexCallMATLAB( 1 , OUTPUT , 2 , INPUT , "feval" ); fevals++; tac( CallMatlab ); } DI = mySize( OUTPUT[0] , 0 ); DJ = mySize( OUTPUT[0] , 1 ); DK = mySize( OUTPUT[0] , 2 ); DIJK = DI*DJ*DK; if( volumes[ NVOLS_1 ] > DIJK ){ if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1]=NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } mxErrMsgTxt("el maximo volumen debe ser menor que numel(DIST)"); } DIJK_1 = DIJK - 1; DIST = (double *) mxGetData( OUTPUT[0] ); DTS = (triplet *) mxRealloc( DTS , DIJK*sizeof( triplet ) ); s = 0; for( kk = 0 ; kk < DK ; kk++ ){ for( jj = 0 ; jj < DJ ; jj++ ){ for( ii = 0 ; ii < DI ; ii++ ){ DTS[ s ].i = ii; DTS[ s ].j = jj; DTS[ s ].k = kk; s++; }}} if( !callSort ){ order = (double *) mxGetData( OUTPUT[1] ); } else { toVec[0] = mxGetNumberOfElements( OUTPUT[0] ); mxSetDimensions( OUTPUT[0] , toVec , 2 ); tic( callSort ); result = mexCallMATLAB( 2 , OUTPUT+1 , 1 , OUTPUT , "sort" ); tac( callSort ); order = (double *) mxGetData( OUTPUT[2] ); } CDI = DTS[ (int) ( order[0] - 1 ) ].i; CDJ = DTS[ (int) ( order[0] - 1 ) ].j; CDK = DTS[ (int) ( order[0] - 1 ) ].k; skip = 0; s = 0; for( n = 0 ; n < NVOLS ; n++ ){ s_end = (int) ( volumes[n] - 1 ); last_distance = DIST[ (int) order[ s_end ] - 1 ]; while( s_end < DIJK_1 && DIST[ (int) ( order[ s_end + 1 ] - 1 ) ] == last_distance ){ s_end++; } s_end++; for( ; s < s_end ; s++ ){ vv = (int) ( order[ s ] - 1 ); ii = T.i + DTS[ vv ].i - CDI; if( ii < 0 || ii > I ){ skip = 1; break; } jj = T.j + DTS[ vv ].j - CDJ; if( jj < 0 || jj > J ){ skip = 1; break; } kk = T.k + DTS[ vv ].k - CDK; if( kk < 0 || kk > K ){ skip = 1; break; } vv = ii + jj*I + kk*IJ; if( TS[ vv ].isnan ){ skip = 1; break; } x = V[ vv ]; if( x < thisMINx ){ thisMINx = x; } y = -x; if( y < thisMINy ){ thisMINy = y; } if( ( thisMINx < LAST_MAX ) && ( thisMINy < LAST_MAX ) ){ skip = 1; break; } } if( skip ){ break; } if( thisMINx > MAXs[n] ){ MAXs[n] = thisMINx; } if( thisMINy > MAXs[n] ){ MAXs[n] = thisMINy; } } LAST_MAX = MAXs[ NVOLS_1 ]; } } if( INPUT[1] != NULL ){ mxDestroyArray( INPUT[1] ); INPUT[1] =NULL; } if( OUTPUT[0] != NULL ){ mxDestroyArray( OUTPUT[0] ); OUTPUT[0]=NULL; } if( OUTPUT[1] != NULL ){ mxDestroyArray( OUTPUT[1] ); OUTPUT[1]=NULL; } if( OUTPUT[2] != NULL ){ mxDestroyArray( OUTPUT[2] ); OUTPUT[2]=NULL; } if( VERBOSE ){ mexPrintf( "\nfevals: %d en tiempo: CallMatlab: %20.30g sorting: %20.30g\n" , fevals , toc( CallMatlab ) , toc( callSort ) ); } if( VV != NULL ){ mxFree( VV ); } if( TS != NULL ){ mxFree( TS ); } if( DTS != NULL ){ mxFree( DTS ); } myFreeALLOCATES(); }
TAC* generateCode(AST* ast) { if(ast == NULL) return NULL; TAC* childTac[4]; childTac[0] = generateCode(ast->child[0]); childTac[1] = generateCode(ast->child[1]); childTac[2] = generateCode(ast->child[2]); childTac[3] = generateCode(ast->child[3]); TAC* result; switch(ast->node_type) { case LITERAL: result = tac(TAC_SYMBOL, ast->node, NULL, NULL); break; case IDENTIFIER: result = tac(TAC_SYMBOL, ast->node, NULL, NULL); break; case ADDITION: result = binaryOp_tac(TAC_ADD, childTac); break; case SUBTRACTION: result = binaryOp_tac(TAC_SUB, childTac); break; case MULTIPLICATION: result = binaryOp_tac(TAC_MUL, childTac); break; case DIVISION: result = binaryOp_tac(TAC_DIV, childTac); break; case LESSERTHAN: result = binaryOp_tac(TAC_LESS, childTac); break; case GREATERTHAN: result = binaryOp_tac(TAC_GREATER, childTac); break; case LESSEREQUAL: result = binaryOp_tac(TAC_LESS_EQUAL, childTac); break; case GREATEREQUAL: result = binaryOp_tac(TAC_GREATER_EQUAL, childTac); break; case EQUAL: result = binaryOp_tac(TAC_EQUAL, childTac); break; case NOTEQUAL: result = binaryOp_tac(TAC_NOT_EQUAL, childTac); break; case AND: result = binaryOp_tac(TAC_AND, childTac); break; case OR: result = binaryOp_tac(TAC_OR, childTac); break; case REF: result = tac(TAC_REF, newTemp(), childTac[0]->destination, NULL); break; case DEREF: result = tac(TAC_DEREF, newTemp(), childTac[0]->destination, NULL); break; case IFTHEN: case IFTHENELSE: result = ifZero_tac(childTac[0], childTac[1], childTac[2]); break; case LOOP: result = loop_tac(childTac[0], childTac[1]); break; case ARRAYACCESS: result = tac(TAC_ARRAYACCESS, childTac[0]->destination, childTac[1]->destination, NULL); break; case ASSIGNMENT: result = assignment_tac(childTac[0], childTac[1]); break; case FUNCTIONCALL: result = call_tac(childTac[0], childTac[1]); break; case ARGUMENTLIST: result = args_tac(childTac); break; case ELEMENTLIST: result = output_args_tac(childTac); break; case RETURN: result = return_tac(childTac[0]); break; case DECLARATION: result = declaration_tac(childTac[1], childTac[2]); break; case ARRAYDECLARATION: result = array_declaration_tac(childTac[1], ast->child[3]); break; case POINTERDECLARATION: result = pointer_declaration_tac(childTac[1],childTac[2]); break; case INPUT: result = tac(TAC_READ, NULL, childTac[0]->destination, NULL); break; case OUTPUT: result = output_tac(childTac[0]); break; case FUNCTIONDEFINITION: result = fun_def_tac(ast->child[0]->child[1]->node, childTac[0], childTac[1], childTac[2]); break; case PARAMETERLIST: result = get_args_tac(childTac); break; case BLOCK: case COMMANDLIST: case PROGRAM: default: result = append(append(append(childTac[0], childTac[1]), childTac[2]), childTac[3]); break; } return result; }