void CONVERT2DECKEY(u32* erk,u32* rk){ int i; /*restore rkeys 1,5,9 */ for(i=0;i<4;i++){ erk[4+i]=erk[44+i]; erk[20+i]=erk[48+i]; erk[36+i]=erk[52+i]; } /* invert the order of the round keys: */ for (i = 0; i < 44; i += 4) { rk[i]= erk[40-i]; rk[i + 1]= erk[41-i]; rk[i + 2]= erk[42- i]; rk[i + 3] = erk[43-i]; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < 10; i++) { rk[4*i] =INVERT(rk[4*i]); rk[4*i+1] =INVERT(rk[4*i+1]); rk[4*i+2] =INVERT(rk[4*i+2]); rk[4*i+3] =INVERT(rk[4*i+3]); } /*copy round keys 1,5,9 in higher memory for reuse*/ for(i=0;i<4;i++){ rk[44+i]=rk[4+i];/*copy r1*/ rk[48+i]=rk[20+i];/*copy r5*/ rk[52+i]=rk[36+i];/*copy r9*/ } }
static void led_task(BT_HANDLE hThread, void *pParam) { bt_kernel_params *kp = bt_get_kernel_params(); BT_kEventGroupWaitBits(kp->init_group, BT_SYSTEM_INIT_USER_READY, BT_FALSE, BT_TRUE, BT_INFINITE_TIMEOUT); BT_GpioSetDirection(BT_CONFIG_ALIVE_LED_GPIO, BT_GPIO_DIR_OUTPUT); BT_TICK ticks = BT_kTickCount(); BT_TICK ticks_a = ticks; while(1) { ticks_a = BT_kTickCount(); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_TRUE)); BT_kTaskDelayUntil(&ticks_a, 10); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_FALSE)); BT_kTaskDelayUntil(&ticks_a, 50); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_TRUE)); BT_kTaskDelayUntil(&ticks_a, 10); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_FALSE)); BT_kTaskDelayUntil(&ticks, BT_CONFIG_ALIVE_LED_PERIOD); } BT_kTaskDelete(NULL); }
Nrrd * _baneGkmsDonNew(int invert) { char me[]="_baneGkmsDonNew", err[BIFF_STRLEN]; Nrrd *ret; float *data; if (nrrdMaybeAlloc_va(ret=nrrdNew(), nrrdTypeFloat, 2, AIR_CAST(size_t, 4), AIR_CAST(size_t, 23))) { sprintf(err, "%s: can't create output", me); biffAdd(BANE, err); return NULL; } data = (float *)ret->data; memcpy(data, _baneGkmsDonData, 4*23*sizeof(float)); data[0 + 4*0] = AIR_NEG_INF; data[0 + 4*1] = AIR_NAN; data[0 + 4*2] = AIR_POS_INF; if (invert) { INVERT(data, 0); INVERT(data, 1); INVERT(data, 2); INVERT(data, 12); INVERT(data, 13); } return ret; }
void Box::mold(QVector3D v, float moldPlateau) { float x = fabs(v.x()); float z = fabs(v.z()); float rad = INVERT(moldPlateau * (m_overallObjectDimensions.y() / 2 +((sqrt(x) * sqrt(z)) + atan2(180, 180) / PI) )/m_overallObjectDimensions.y()); v.setX(v.x() * rad); v.setZ(v.z() * rad); glVertex3fv(&v[0]); }
static void led_task(void *pParam) { BT_GpioSetDirection(BT_CONFIG_ALIVE_LED_GPIO, BT_GPIO_DIR_OUTPUT); BT_TICK ticks = BT_kTickCount(); BT_TICK ticks_a = ticks; while(1) { ticks_a = BT_kTickCount(); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_TRUE)); BT_kTaskDelayUntil(&ticks_a, 10); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_FALSE)); BT_kTaskDelayUntil(&ticks_a, 50); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_TRUE)); BT_kTaskDelayUntil(&ticks_a, 10); BT_GpioSet(BT_CONFIG_ALIVE_LED_GPIO, INVERT(BT_FALSE)); BT_kTaskDelayUntil(&ticks, BT_CONFIG_ALIVE_LED_PERIOD); } BT_kTaskDelete(NULL); }
bst128 TAES_DECRYPT(bst128 in,u32* rkd,bst128 counter){ bst128 out; int i; u32 tempcounter; /*apply the inverse matrix mult to counter */ for(i=0;i<4;i++){ tempcounter=INVERT(counter.t[i]); /*set rkeys 1,5,9 using the backups*/ rkd[4+i]=rkd[44+i]^tempcounter; rkd[20+i]=rkd[48+i]^tempcounter; rkd[36+i]=rkd[52+i]^tempcounter; } rijndaelDecrypt(rkd,in.b,out.b); return out; }
void DIMENSION::Mirror( const wxPoint& axis_pos ) { wxPoint newPos = m_Text.GetTextPosition(); #define INVERT( pos ) (pos) = axis_pos.y - ( (pos) - axis_pos.y ) INVERT( newPos.y ); m_Text.SetTextPosition( newPos ); // invert angle m_Text.SetOrientation( -m_Text.GetOrientation() ); INVERT( m_crossBarO.y ); INVERT( m_crossBarF.y ); INVERT( m_featureLineGO.y ); INVERT( m_featureLineGF.y ); INVERT( m_featureLineDO.y ); INVERT( m_featureLineDF.y ); INVERT( m_arrowG1F.y ); INVERT( m_arrowG2F.y ); INVERT( m_arrowD1F.y ); INVERT( m_arrowD2F.y ); }
void mupip_upgrade(void) { bool rbno; unsigned char *upgrd_buff[2], upgrd_label[GDS_LABEL_SZ]="UPGRADE0304"; char fn[256]; char answer[4]; unsigned short fn_len; int4 fd, save_errno, old_hdr_size, new_hdr_size, status, bufsize, dsize, datasize[2]; int4 old_hdr_size_vbn, new_hdr_size_vbn; int fstat_res; off_t last_full_grp_startoff, old_file_len, old_file_len2, read_off, write_off, old_start_vbn_off; block_id last_full_grp_startblk; v3_sgmnt_data old_head_data, *old_head; sgmnt_data new_head_data, *new_head; struct stat stat_buf; error_def(ERR_MUNODBNAME); error_def(ERR_MUNOUPGRD); error_def(ERR_DBOPNERR); error_def(ERR_DBRDONLY); error_def(ERR_DBFILOPERR); error_def(ERR_DBPREMATEOF); ESTABLISH(mupip_upgrade_ch); fn_len = sizeof(fn); if (!cli_get_str("FILE", fn, &fn_len)) rts_error(VARLSTCNT(1) ERR_MUNODBNAME); if (!(mupip_upgrade_standalone(fn, &upgrade_standalone_sems))) rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); if (-1 == (fd = OPEN(fn, O_RDWR))) { save_errno = errno; if (-1 != (fd = OPEN(fn, O_RDONLY))) { util_out_print("Cannot update read-only database.", FLUSH); rts_error(VARLSTCNT(5) ERR_DBRDONLY, 2, fn_len, fn, errno); } rts_error(VARLSTCNT(5) ERR_DBRDONLY, 2, fn_len, fn, save_errno); } /* Confirm before proceed */ if (!mu_upgrd_confirmed(TRUE)) { util_out_print("Upgrade canceled by user", FLUSH); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } util_out_print("Do not interrupt to avoid damage in database!!", FLUSH); util_out_print("Mupip upgrade started ...!/", FLUSH); mu_upgrd_sig_init(); /* get file status */ FSTAT_FILE(fd, &stat_buf, fstat_res); if (-1 == fstat_res) rts_error(VARLSTCNT(5) ERR_DBOPNERR, 2, fn_len, fn, errno); old_file_len = stat_buf.st_size; /* Prepare v3.x file header buffer */ old_hdr_size = sizeof(*old_head); old_head = &old_head_data; /* Prepare v4.x file header buffer */ new_hdr_size = sizeof(*new_head); new_head = &new_head_data; memset(new_head, 0, new_hdr_size); old_hdr_size_vbn = DIVIDE_ROUND_UP(old_hdr_size, DISK_BLOCK_SIZE); new_hdr_size_vbn = DIVIDE_ROUND_UP(new_hdr_size, DISK_BLOCK_SIZE); /* READ header from V3.x file */ LSEEKREAD(fd, 0, old_head, old_hdr_size, status); if (0 != status) if (-1 == status) rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); else rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); /* Check version */ if (memcmp(&old_head->label[0], GDS_LABEL, GDS_LABEL_SZ - 1)) { if (memcmp(&old_head->label[0], GDS_LABEL, GDS_LABEL_SZ - 3)) { /* it is not a GTM database */ close(fd); util_out_print("File !AD is not a GT.M database.!/", FLUSH, fn_len, fn); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); }else { /* it is GTM database */ /* is it not v3.x database? */ if (memcmp(&old_head->label[GDS_LABEL_SZ - 3],GDS_V30,2) !=0 && memcmp(&old_head->label[GDS_LABEL_SZ - 3],GDS_ALT_V30,2) != 0) { close(fd); util_out_print("File !AD has an unrecognized database version!/", FLUSH, fn_len, fn); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } } } else { /* Note: We assume that if the V4.x header and current GT.M file header * has same field names, they are at same offset */ /* READ the header from file again as V4.x header */ LSEEKREAD(fd, 0, new_head, new_hdr_size, status); if (0 != status) if (-1 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); else rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); if (QWNE(new_head->reg_seqno, seq_num_zero) || QWNE(new_head->resync_seqno, seq_num_zero) || (new_head->resync_tn != 0) || new_head->repl_state != repl_closed) { util_out_print("!AD might already have been upgraded", FLUSH, fn_len, fn); util_out_print("Do you wish to continue with the upgrade? [y/n] ", FLUSH); SCANF("%s", answer); if (answer[0] != 'y' && answer[0] != 'Y') { close(fd); util_out_print("Upgrade canceled by user", FLUSH); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } } init_replication(new_head); new_head->max_update_array_size = new_head->max_non_bm_update_array_size = ROUND_UP2(MAX_NON_BITMAP_UPDATE_ARRAY_SIZE(new_head), UPDATE_ARRAY_ALIGN_SIZE); new_head->max_update_array_size += ROUND_UP2(MAX_BITMAP_UPDATE_ARRAY_SIZE, UPDATE_ARRAY_ALIGN_SIZE); new_head->mutex_spin_parms.mutex_hard_spin_count = MUTEX_HARD_SPIN_COUNT; new_head->mutex_spin_parms.mutex_sleep_spin_count = MUTEX_SLEEP_SPIN_COUNT; new_head->mutex_spin_parms.mutex_spin_sleep_mask = MUTEX_SPIN_SLEEP_MASK; new_head->semid = INVALID_SEMID; new_head->shmid = INVALID_SHMID; if (JNL_ALLOWED(new_head)) { /* Following 3 are new fields starting from V43001. * Initialize them appropriately. */ new_head->epoch_interval = DEFAULT_EPOCH_INTERVAL; new_head->alignsize = DISK_BLOCK_SIZE * JNL_DEF_ALIGNSIZE; if (!new_head->jnl_alq) new_head->jnl_alq = JNL_ALLOC_DEF; /* note new_head->jnl_deq is carried over without any change even if it is zero since a zero * jnl file extension size is supported starting V43001 */ new_head->autoswitchlimit = ALIGNED_ROUND_DOWN(JNL_ALLOC_MAX, new_head->jnl_alq, new_head->jnl_deq); /* following field is assumed as non-zero by set_jnl_info starting V43001A */ if (JNL_ALLOWED(new_head) && !new_head->jnl_buffer_size) new_head->jnl_buffer_size = JNL_BUFFER_DEF; } else { new_head->epoch_interval = 0; new_head->alignsize = 0; new_head->autoswitchlimit = 0; } new_head->yield_lmt = DEFAULT_YIELD_LIMIT; /* writing header */ LSEEKWRITE(fd, 0, new_head, new_hdr_size, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); close(fd); util_out_print("File !AD successfully upgraded.!/", FLUSH, fn_len, fn); if (0 != sem_rmid(upgrade_standalone_sems)) { util_out_print("Error with sem_rmid : %d [0x%x]", TRUE, upgrade_standalone_sems, upgrade_standalone_sems); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } mupip_exit(SS_NORMAL); } util_out_print("Old header size: !SL", FLUSH, old_hdr_size); util_out_print("New header size: !SL", FLUSH, new_hdr_size); if (old_head->createinprogress) { close(fd); util_out_print("Database creation in progress on file !AD.!/", FLUSH, fn_len, fn); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } if (old_head->file_corrupt) { close(fd); util_out_print("Database !AD is corrupted.!/", FLUSH, fn_len, fn); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } if ((((off_t)old_head->start_vbn - 1) * DISK_BLOCK_SIZE + (off_t)old_head->trans_hist.total_blks * old_head->blk_size + (off_t)DISK_BLOCK_SIZE != old_file_len) && (((off_t)old_head->start_vbn - 1) * DISK_BLOCK_SIZE + (off_t)old_head->trans_hist.total_blks * old_head->blk_size + (off_t)old_head->blk_size != old_file_len)) { util_out_print("Incorrect start_vbn !SL or, block size !SL or, total blocks !SL", FLUSH, old_head->start_vbn, old_head->blk_size, old_head->trans_hist.total_blks); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } if (ROUND_DOWN(old_head->blk_size, DISK_BLOCK_SIZE) != old_head->blk_size) { util_out_print("Database block size !SL is not divisible by DISK_BLOCK_SIZE", FLUSH, old_head->blk_size); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } mu_upgrd_header(old_head, new_head); /* Update header from v3.x to v4.x */ new_head->start_vbn = new_hdr_size_vbn + 1; new_head->free_space = 0; new_head->wc_blocked_t_end_hist.evnt_cnt = old_head->wc_blocked_t_end_hist2.evnt_cnt; new_head->wc_blocked_t_end_hist.evnt_tn = old_head->wc_blocked_t_end_hist2.evnt_tn; init_replication(new_head); /* A simple way of doing mupip upgrade is to move all the data after file header towards the eof to make space and write down the header. This does not need any computation or, change in data/index blocks. This is a slow process because it has mainly I/O, though no manipulation of database structures. or index blocks. This is okay for small database. A time efficient way is to physically move second group of BLKS_PER_LMAP number of blocks towards the eof and move first group of BLKS_PER_LMAP number of blocks in place of 2nd group. Finally adjust all indices to point to the blocks correctly. Also adjust master bit map. (note: we cannot move first group from the beginning). Detail algorithm as follows: --------------------------- // Allocate two buffers each to hold one group of data. Read v3.x header and upgrade to v4.x if file is big enough read group 1 in buff[0] read_off = offset of starting block of 2nd group. read group 2 in buff[1] write buff[0] at offset read_off last_full_grp_startblk = points to the block where 2nd group of 512 blocks of old file will be written back. //Instead of searching for a free group we will write at the last full group //Say, we have 3000 blocks. last_full_grp_startblk = 2048 // (not 2560, because it is not full) //All data from that point upto eof will be read and saved in buffer read all remaining data from the point last_full_grp_startblk upto eof in buff[0] write buff[1] at the point of last_full_grp_startblk Now write buff[0] at the end of last write //Graphical Example: Each letter corresponds to a group of 512 blocks where first block // is local bit map. Last group U may be a group of less than 512 blocks. // Extend towards right -------------------------------------------------------> // old permutation: [v3 head] A B C D E F G H I J K L M N O P Q R S T U // new permutation: [v4 head ] A C D E F G H I J K L M N O P Q R S T B U Finally traverse the tree and adjust block pointers Adjust master map write new v4.x header at bof else bufsize = size of data for a group rbno = 0 // read buffer no. This switches between 0 and 1 read_off = 0 write_off = 0 upgrd_buff[rbno] = new header data_size[rbno] = new header size rbno = INVERT(rbno); do while not eof data_size[rbno] = MIN(bufsize, remaining_data_size) Read data of size data_size[rbno] in upgrd_buff[rbno] and adjust read_off rbno = INVERT(rbno); Write upgrd_buff[rbno] of datasize[rbno] at write_off and increase write_off Enddo rbno = INVERT(rbno) Write upgrd_buff[rbno] of datasize[rbno] at write_off endif */ bufsize = old_head->blk_size * BLKS_PER_LMAP; upgrd_buff[0] = (unsigned char*) malloc(bufsize); upgrd_buff[1] = (unsigned char*) malloc(bufsize); read_off = old_start_vbn_off = (off_t)(old_head->start_vbn - 1) * DISK_BLOCK_SIZE; /* start vbn offset in bytes */ last_full_grp_startblk = ROUND_DOWN(new_head->trans_hist.total_blks, BLKS_PER_LMAP); /* in block_id */ last_full_grp_startoff = old_start_vbn_off + (off_t)last_full_grp_startblk * new_head->blk_size; /* offset in bytes */ /* this calculation is used because some 3.2x database has GDS blk_size bytes at the end instead of DISK_BLOCK_SIZE bytes. */ old_file_len2 = old_head->start_vbn * DISK_BLOCK_SIZE + (off_t)old_head->blk_size * old_head->trans_hist.total_blks; /* Change Label to a temporary dummy value, so that other GTM process does not come while doing upgrade and corrupts database */ LSEEKWRITE(fd, 0, upgrd_label, GDS_LABEL_SZ - 1, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); if (old_head->trans_hist.total_blks > BLKS_PER_LMAP * 2) { /* recalculate start_vbn and free space, because there will be a gap after header */ new_head->start_vbn = old_head->start_vbn + bufsize / DISK_BLOCK_SIZE; new_head->free_space = bufsize - (new_hdr_size_vbn - old_hdr_size_vbn) * DISK_BLOCK_SIZE; util_out_print("New starting VBN is: !SL !/", FLUSH, new_head->start_vbn); /* read 1st group of blocks */ LSEEKREAD(fd, read_off, upgrd_buff[0], bufsize, status); if (0 != status) if (-1 == status) rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); else rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); read_off = read_off + bufsize; /* read 2nd group of blocks */ LSEEKREAD(fd, read_off, upgrd_buff[1], bufsize, status); if (0 != status) if (-1 == status) rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); else rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); /* write 1st group of blocks in place of 2nd group */ write_off = old_start_vbn_off + bufsize; LSEEKWRITE(fd, write_off, upgrd_buff[0], bufsize, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); /* read last group (# of blks <= BLKS_PER_LMAP) */ dsize = old_file_len2 - last_full_grp_startoff; assert (dsize <= bufsize); LSEEKREAD(fd, last_full_grp_startoff, upgrd_buff[0], dsize, status); if (0 != status) if (-1 == status) rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); else rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); /* write 2nd group of blocks */ LSEEKWRITE(fd, last_full_grp_startoff, upgrd_buff[1], bufsize, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); /* write last group read from old file */ LSEEKWRITE(fd, last_full_grp_startoff + bufsize, upgrd_buff[0], dsize, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); util_out_print("Please wait while index is being adjusted...!/", FLUSH); mu_upgrd_adjust_blkptr(1L, TRUE, new_head, fd, fn, fn_len); mu_upgrd_adjust_mm(new_head->master_map, DIVIDE_ROUND_UP(new_head->trans_hist.total_blks+1,BLKS_PER_LMAP)); /* writing header */ LSEEKWRITE(fd, 0, new_head, new_hdr_size, status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); } else /* very small database */ { rbno = 0; write_off = 0; datasize[rbno] = new_hdr_size; memcpy(upgrd_buff[0], new_head, new_hdr_size); rbno = INVERT(rbno); while(read_off < old_file_len2) { datasize[rbno] = MIN (old_file_len2 - read_off, bufsize); LSEEKREAD(fd, read_off, upgrd_buff[rbno], datasize[rbno], status); if (0 != status) if (-1 == status) rts_error(VARLSTCNT(4) ERR_DBPREMATEOF, 2, fn_len, fn); else rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); read_off += datasize[rbno]; rbno = INVERT(rbno); LSEEKWRITE(fd, write_off, upgrd_buff[rbno], datasize[rbno], status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); write_off+= datasize[rbno]; } rbno = INVERT(rbno); LSEEKWRITE(fd, write_off, upgrd_buff[rbno], datasize[rbno], status); if (0 != status) rts_error(VARLSTCNT(5) ERR_DBFILOPERR, 2, fn_len, fn, status); } /* end if small database */ free(upgrd_buff[0]); free(upgrd_buff[1]); close(fd); util_out_print("File !AD successfully upgraded.!/", FLUSH, fn_len, fn); REVERT; if (0 != sem_rmid(upgrade_standalone_sems)) { util_out_print("Error with sem_rmid : %d [0x%x]", TRUE, upgrade_standalone_sems, upgrade_standalone_sems); rts_error(VARLSTCNT(1) ERR_MUNOUPGRD); } mupip_exit(SS_NORMAL); }
/* update ellipsoid according to the given motion */ void ELLIP_Update (ELLIP *eli, void *body, void *shp, MOTION motion) { SGP sgp = {shp, eli, GOBJ_ELLIP, NULL}; double *ref = eli->ref_center, (*ref_pnt) [3] = eli->ref_point, *cur = eli->cur_center, (*cur_pnt) [3] = eli->cur_point; if (motion) { motion (body, &sgp, ref, cur); motion (body, &sgp, ref_pnt [0], cur_pnt [0]); motion (body, &sgp, ref_pnt [1], cur_pnt [1]); motion (body, &sgp, ref_pnt [2], cur_pnt [2]); BODY *bod = body; switch (bod->kind) { case OBS: case RIG: { double *R1 = bod->conf, *R0 = eli->ref_rot, *rot = eli->cur_rot; NNMUL (R1, R0, rot); } break; case PRB: { double *F = bod->conf, *sca0 = eli->ref_sca, *rot0 = eli->ref_rot, *sca1 = eli->cur_sca, *rot1 = eli->cur_rot; double U[9] = {1.0/(sca0[0]*sca0[0]), 0.0, 0.0, 0.0, 1.0/(sca0[1]*sca0[1]), 0.0, 0.0, 0.0, 1.0/(sca0[2]*sca0[2])}; double A0[9], iF[9], det, X[3], Y[9], A[9]; NTMUL (U, rot0, Y); NNMUL (rot0, Y, A0); TNCOPY (F, Y); /* T --> since deformation gradient is stored row-wise */ INVERT (Y, iF, det); ASSERT_TEXT (det > 0.0, "det(F) <= 0.0 during ellipsoid update"); NNMUL (A0, iF, Y); TNMUL (iF, Y, A); ASSERT_TEXT (lapack_dsyev ('V', 'U', 3, A, 3, X, Y, 9) == 0, "Eigen decomposition failed during ellipsoid update"); if (DET(A) < 0.0) /* det(A) is 1.0 or -1.0 */ { SCALE9 (A, -1.0); /* keep positive space orientation */ } NNCOPY (A, rot1); sca1[0] = 1.0/sqrt(X[0]); sca1[1] = 1.0/sqrt(X[1]); sca1[2] = 1.0/sqrt(X[2]); } break; default: { ASSERT_TEXT (0, "Invalid body kind during ellipsoid update"); } break; } } else { COPY (ref, cur); COPY (ref_pnt [0], cur_pnt [0]); COPY (ref_pnt [1], cur_pnt [1]); COPY (ref_pnt [2], cur_pnt [2]); sca_rot (eli->ref_center, eli->ref_point, eli->ref_sca, eli->ref_rot); COPY (eli->ref_sca, eli->cur_sca); NNCOPY (eli->ref_rot, eli->cur_rot); } }