void tex::math_left_right () { ptr p; int t; mcell garbage; t = cur_chr; if (t == RIGHT_NOAD && cur_group != MATH_LEFT_GROUP) { if (cur_group == MATH_SHIFT_GROUP) { scan_delimiter((ptr)&garbage, FALSE); print_err("Extra "); print_esc("right"); help_xtra_right(); error(); } else { off_save(); } } else { p = new_noad(); type(p) = t; scan_delimiter(delimiter(p), FALSE); if (t == LEFT_NOAD) { push_math(MATH_LEFT_GROUP); tail = link(head) = p; } else { p = fin_mlist(p); unsave(); tail_append(new_noad()); type(tail) = INNER_NOAD; math_type(nucleus(tail)) = SUB_MLIST; math_link(nucleus(tail)) = p; } } }
void tex::math_ac () { if (cur_cmd == ACCENT) { print_err("Please use "); print_esc("mathaccent"); print(" for accents in math mode"); help_math_accent(); error(); } tail_append(new_node(ACCENT_NOAD_SIZE)); type(tail) = ACCENT_NOAD; subtype(tail) = NORMAL; mzero(nucleus(tail)); mzero(subscr(tail)); mzero(supscr(tail)); math_type(accent_chr(tail)) = MATH_CHAR; scan_fifteen_bit_int(); character(accent_chr(tail)) = cur_val % 256; if (cur_val >= VAR_CODE && fam_in_range()) { fam(accent_chr(tail)) = cur_fam; } else { fam(accent_chr(tail)) = cur_val / 256 % 16; } scan_math(nucleus(tail)); }
void tex::set_math_char(int c) { ptr p; if (c >= 0100000) { cur_cs = active_base[cur_chr]; cur_cmd = eq_type(cur_cs); cur_chr = equiv(cur_cs); x_token(); back_input(); } else { p = new_noad(); math_type(nucleus(p)) = MATH_CHAR; character(nucleus(p)) = c % 256; fam(nucleus(p)) = c / 256 % 16; if (c >= VAR_CODE) { if (fam_in_range()) fam(nucleus(p)) = cur_fam; type(p) = ORD_NOAD; } else { type(p) = ORD_NOAD + c / 010000; } tail_append(p); } }
void tex::math_radical () { tail_append(new_node(RADICAL_NOAD_SIZE)); type(tail) = RADICAL_NOAD; subtype(tail) = NORMAL; mzero(nucleus(tail)); mzero(supscr(tail)); mzero(subscr(tail)); scan_delimiter(left_delimiter(tail), TRUE); scan_math(nucleus(tail)); }
void tex::indent_in_hmode () { ptr p, q; if (cur_chr > 0) { p = new_null_box(); box_width(p) = par_indent; if (abs(mode) == HMODE) { space_factor = 1000; } else { q = new_noad(); math_type(nucleus(q)) = SUB_BOX; math_link(nucleus(q)) = p; p = q; } tail_append(p); } }
//============================================================================== // MAIN int main( int argc, char* argv[] ) { // spatial dimension const unsigned dim = SPACEDIM; typedef base::solver::Eigen3 Solver; // Check input arguments if ( argc != 2 ) { std::cerr << "Usage: " << argv[0] << " input.dat\n" << "(Compiled for dim=" << dim << ")\n\n"; return -1; } // read name of input file const std::string inputFile = boost::lexical_cast<std::string>( argv[1] ); const InputNucleus<dim> ui( inputFile ); // Simulation attributes const bool simplex = false; const bool stokesStabil = false; typedef mat::hypel::NeoHookeanCompressible Material; typedef TypesAndAttributes<dim,simplex> TA; // basic attributes of the computation base::auxi::BoundingBox<dim> bbox( ui.bbmin, ui.bbmax ); TA::Mesh mesh; generateMesh( mesh, ui ); // Creates a list of <Element,faceNo> pairs base::mesh::MeshBoundary meshBoundary; meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() ); TA::BoundaryMesh boundaryMesh; base::mesh::generateBoundaryMesh( meshBoundary.begin(), meshBoundary.end(), mesh, boundaryMesh ); // mesh size (all equal, more or less) const double h = base::mesh::Size<TA::Mesh::Element>::apply( mesh.elementPtr(0) ); //-------------------------------------------------------------------------- typedef base::cut::LevelSet<dim> LevelSet; std::vector<LevelSet> levelSetNucleus, levelSetMembrane; base::cut::analyticLevelSet( mesh, base::cut::Sphere<dim>( ui.RN, ui.centerN ), true, levelSetNucleus ); base::cut::analyticLevelSet( mesh, base::cut::Sphere<dim>( ui.RM, ui.centerM ), true, levelSetMembrane ); //-------------------------------------------------------------------------- // make cut cell structures std::vector<TA::Cell> cellsNucleus, cellsMembrane, cellsCS; base::cut::generateCutCells( mesh, levelSetNucleus, cellsNucleus ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane ); { cellsCS = cellsNucleus; std::for_each( cellsCS.begin(), cellsCS.end(), boost::bind( &TA::Cell::reverse, _1 ) ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS, base::cut::INTERSECT ); } // intersection with the box boundary std::vector<TA::SurfCell> surfaceCells; base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells ); // Elastic material Material material( mat::Lame::lambda( ui.E, ui.nu), mat::Lame::mu( ui.E, ui.nu ) ); // Solid and fluid handlers typedef Solid<TA::Mesh, Material> Solid; typedef Fluid<TA::Mesh, stokesStabil> Fluid; typedef SolidFluidInterface<TA::SurfaceMesh,Solid,Fluid> SFI; typedef FluidFluidInterface<TA::SurfaceMesh,Fluid> FFI; Solid nucleus( mesh, material ); Fluid gel( mesh, ui.viscosityGel, ui.alpha ); Fluid cytoSkeleton( mesh, ui.viscosityCS, ui.alpha ); // find geometry association for the dofs std::vector<std::pair<std::size_t,TA::VecDim> > doFLocationD, doFLocationU; base::dof::associateLocation( nucleus.getDisplacement(), doFLocationD ); base::dof::associateLocation( gel.getVelocity(), doFLocationU ); // Quadrature along a surface TA::CutQuadrature cutQuadratureNucleus( cellsNucleus, true ); TA::CutQuadrature cutQuadratureGel( cellsMembrane, false ); TA::CutQuadrature cutQuadratureCS( cellsCS, true ); TA::SurfaceQuadrature surfaceQuadrature; TA::SurfCutQuadrature surfaceCutQuadrature( surfaceCells, true ); //-------------------------------------------------------------------------- // Run a zero-th step in order to write the data before computation // (store the previously enclosed volume) double prevVolumeN, initialVolumeCS; { std::cout << 0 << " " << 0. << " 0 " << std::flush; writeVTKFile( "nucleus", 0, mesh, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), levelSetNucleus, levelSetMembrane, ui.dt ); // for surface field TA::SurfaceMesh membrane, envelope; base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane ); base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus, envelope ); writeSurfaceVTKFile( "membrane", 0, membrane ); writeSurfaceVTKFile( "envelope", 0, envelope ); surfaceFeatures( boundaryMesh, membrane, envelope, surfaceQuadrature, surfaceCutQuadrature, std::cout ); std::cout << std::endl; // store the contained volume prevVolumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); initialVolumeCS = surf::enclosedVolume( membrane, surfaceQuadrature ) + surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature ); } //-------------------------------------------------------------------------- // * Loop over time steps * //-------------------------------------------------------------------------- const double supportThreshold = std::numeric_limits<double>::min(); for ( unsigned step = 0; step < ui.numLoadSteps; step++ ) { // for surface field TA::SurfaceMesh membrane, envelope; base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane ); base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus, envelope ); // Interface handler SFI envelopeHandler( envelope, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), ui.viscosityCS ); FFI membraneHandler( membrane, cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), cellsMembrane, ui.viscosityCS, ui.viscosityGel, ui.sigma ); std::cout << step+1 << " " << (step+1) * ui.dt << " " << std::flush; //---------------------------------------------------------------------- // 0) Solve Lagrangian problem // compute supports std::vector<double> supportsD, supportsUCS, supportsPCS, supportsUGel, supportsPGel; base::cut::supportComputation( mesh, nucleus.getDisplacement(), cutQuadratureNucleus, supportsD ); base::cut::supportComputation( mesh, cytoSkeleton.getVelocity(), cutQuadratureCS, supportsUCS ); base::cut::supportComputation( mesh, cytoSkeleton.getPressure(), cutQuadratureCS, supportsPCS ); base::cut::supportComputation( mesh, gel.getVelocity(), cutQuadratureGel, supportsUGel ); base::cut::supportComputation( mesh, gel.getPressure(), cutQuadratureGel, supportsPGel ); // Hard-wired Dirichlet constraints (fluid BC) { // apply to outer material = gel base::dof::constrainBoundary<Fluid::FEBasisU>( meshBoundary.begin(), meshBoundary.end(), mesh, gel.getVelocity(), boost::bind( &dirichletBC<dim,Fluid::DoFU>, _1, _2, ui.ubar, bbox, ui.bc ) ); // in case of boundary intersections, apply to cytoskeleton base::dof::constrainBoundary<Fluid::FEBasisU>( meshBoundary.begin(), meshBoundary.end(), mesh, cytoSkeleton.getVelocity(), boost::bind( &dirichletBC<dim,Fluid::DoFU>, _1, _2, ui.ubar, bbox, ui.bc ) ); // Fix first pressure dof in case of closed cavity flow if ( ui.bc == CAVITY ) { Fluid::Pressure::DoFPtrIter pIter = gel.getPressure().doFsBegin(); (*pIter) -> constrainValue( 0, 0.0 ); } } // Basis stabilisation base::cut::stabiliseBasis( mesh, nucleus.getDisplacement(), supportsD, doFLocationD ); base::cut::stabiliseBasis( mesh, cytoSkeleton.getVelocity(), supportsUCS, doFLocationU ); base::cut::stabiliseBasis( mesh, cytoSkeleton.getPressure(), supportsPCS, doFLocationD ); base::cut::stabiliseBasis( mesh, gel.getVelocity(), supportsUGel, doFLocationU ); base::cut::stabiliseBasis( mesh, gel.getPressure(), supportsPGel, doFLocationD ); // number DoFs const std::size_t activeDoFsD = base::dof::numberDoFsConsecutively( nucleus.getDisplacement().doFsBegin(), nucleus.getDisplacement().doFsEnd() ); const std::size_t activeDoFsUCS = base::dof::numberDoFsConsecutively( cytoSkeleton.getVelocity().doFsBegin(), cytoSkeleton.getVelocity().doFsEnd(), activeDoFsD ); const std::size_t activeDoFsPCS = base::dof::numberDoFsConsecutively( cytoSkeleton.getPressure().doFsBegin(), cytoSkeleton.getPressure().doFsEnd(), activeDoFsD + activeDoFsUCS ); const std::size_t activeDoFsUGel = base::dof::numberDoFsConsecutively( gel.getVelocity().doFsBegin(), gel.getVelocity().doFsEnd(), activeDoFsD + activeDoFsUCS + activeDoFsPCS ); const std::size_t activeDoFsPGel = base::dof::numberDoFsConsecutively( gel.getPressure().doFsBegin(), gel.getPressure().doFsEnd(), activeDoFsD + activeDoFsUCS + activeDoFsPCS + activeDoFsUGel ); // start from 0 for the increments, set rest to zero too base::dof::clearDoFs( nucleus.getDisplacement() ); base::dof::clearDoFs( cytoSkeleton.getPressure() ); base::dof::clearDoFs( cytoSkeleton.getVelocity() ); base::dof::clearDoFs( gel.getPressure() ); base::dof::clearDoFs( gel.getVelocity() ); //---------------------------------------------------------------------- // Nonlinear iterations unsigned iter = 0; for ( ; iter < ui.maxIter; iter++ ) { // Create a solver object Solver solver( activeDoFsD + activeDoFsUCS + activeDoFsPCS + activeDoFsUGel + activeDoFsPGel ); // register to solver nucleus.registerInSolver( solver ); cytoSkeleton.registerInSolver( solver ); gel.registerInSolver( solver ); membraneHandler.registerInSolver( solver ); envelopeHandler.registerInSolver( solver ); // Compute as(d,dd) and Da(d,dd)[Delta d] nucleus.assembleBulk( cutQuadratureNucleus, solver, iter ); // Body force nucleus.bodyForce( cutQuadratureNucleus, solver, boost::bind( unitForce<0,dim>, _1, ui.forceValue ) ); // Computate af(u,p; du,dp) cytoSkeleton.assembleBulk( cutQuadratureCS, solver ); gel.assembleBulk( cutQuadratureGel, solver ); // Penalty terms for int_Gamma (dot(d) - u) (E delta d - mu delta u) ds envelopeHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac, ui.dt ); membraneHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac ); // Boundary energy terms (beta = 0) [ -int_Gamma (...) ds ] envelopeHandler.assembleEnergyTerms( surfaceQuadrature, solver, ui.dt ); membraneHandler.assembleEnergyTerms( surfaceQuadrature, solver ); // surface tension membraneHandler.surfaceTension( surfaceQuadrature, solver ); // Finalise assembly solver.finishAssembly(); // norm of residual const double conv1 = solver.norm(0, activeDoFsD) / ui.E; if ( isnan( conv1 ) ) return 1; if ( ( iter > 0 ) and ( conv1 < ui.tolerance ) ) { std::cout << "schon" << std::endl; break; } // Solve #ifdef LOAD_PARDISO solver.pardisoLUSolve(); #else #ifdef LOAD_UMFPACK solver.umfPackLUSolve(); #else solver.superLUSolve(); //solver.biCGStabSolve(); #endif #endif // distribute results back to dofs base::dof::addToDoFsFromSolver( solver, nucleus.getDisplacement() ); //<> base::dof::setDoFsFromSolver( solver, cytoSkeleton.getVelocity() ); base::dof::setDoFsFromSolver( solver, cytoSkeleton.getPressure() ); base::dof::setDoFsFromSolver( solver, gel.getVelocity() ); base::dof::setDoFsFromSolver( solver, gel.getPressure() ); const double conv2 = solver.norm(0, activeDoFsD); if ( conv2 < ui.tolerance ) break; } // finish non-linear iteration std::cout << iter << " " << std::flush; // write a vtk file writeVTKFile( "nucleus", step+1, mesh, nucleus.getDisplacement(), cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(), gel.getVelocity(), gel.getPressure(), levelSetNucleus, levelSetMembrane, ui.dt ); writeSurfaceVTKFile( "membrane", step+1, membrane ); writeSurfaceVTKFile( "envelope", step+1, envelope ); //---------------------------------------------------------------------- // 1) Pass Data to complementary domain of solid { const double extL = h; // extrapolation length // pass extrapolated solution to inactive DoFs extrapolateToFictitious( mesh, nucleus.getDisplacement(), extL, doFLocationD, levelSetNucleus, bbox ); } //---------------------------------------------------------------------- // 2) Geometry update // a) Nucleus { // get shape features const double volumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); const TA::VecDim momentN = surf::enclosedVolumeMoment( envelope, surfaceQuadrature ); const TA::VecDim centroidN = momentN / volumeN; const double factorN = std::pow( prevVolumeN / volumeN, 1./static_cast<double>( dim ) ); // Move with velocity solution moveSurface( mesh, cytoSkeleton.getVelocity(), envelope, ui.dt, factorN, centroidN ); // compute new level set for envelope of nucleus base::cut::bruteForce( mesh, envelope, true, levelSetNucleus ); // update the cut cell structure base::cut::generateCutCells( mesh, levelSetNucleus, cellsNucleus ); // store the contained volume prevVolumeN = surf::enclosedVolume( envelope, surfaceQuadrature ); } // b) CS { // get shape features const double volumeCS = surf::enclosedVolume( membrane, surfaceQuadrature ) + surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature ); const TA::VecDim momentCS = surf::enclosedVolumeMoment( membrane, surfaceQuadrature ) + surf::enclosedVolumeMoment( boundaryMesh, surfaceCutQuadrature ); const TA::VecDim centroidCS = momentCS / volumeCS; // Move with velocity solution moveSurface( mesh, gel.getVelocity(), membrane, ui.dt, 1.0, centroidCS ); // rescale in order to preserve initial volume rescaleSurface( membrane, initialVolumeCS, volumeCS, centroidCS ); // compute new level set for membrane base::cut::bruteForce( mesh, membrane, true, levelSetMembrane ); // update the cut cell structure base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane ); base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells ); } // new structure for cytoskeleton { cellsCS = cellsNucleus; std::for_each( cellsCS.begin(), cellsCS.end(), boost::bind( &TA::Cell::reverse, _1 ) ); base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS, base::cut::INTERSECT ); } //---------------------------------------------------------------------- // 3) advect data { base::cut::supportComputation( mesh, nucleus.getDisplacement(), cutQuadratureNucleus, supportsD ); // Find the location of the DoFs in the previous configuration std::vector<std::pair<std::size_t,TA::VecDim> > previousDoFLocation; findPreviousDoFLocations( mesh, nucleus.getDisplacement(), supportsD, doFLocationD, previousDoFLocation, bbox, supportThreshold, ui.findTolerance, 10 ); // add previous solution to current solution: u_{n+1} = \Delta u + u_n { Solid::Displacement::DoFPtrIter dIter = nucleus.getDisplacement().doFsBegin(); Solid::Displacement::DoFPtrIter dEnd = nucleus.getDisplacement().doFsEnd(); for ( ; dIter != dEnd; ++dIter ) { for ( unsigned d = 0; d < dim; d++ ) { const double prevU = (*dIter) -> getHistoryValue<1>( d ); const double deltaU = (*dIter) -> getHistoryValue<0>( d ); const double currU = prevU + deltaU; (*dIter) -> setValue( d, currU ); } } } // advect displacement field from previous to new location advectField( mesh, nucleus.getDisplacement(), previousDoFLocation, supportsD, supportThreshold ); } //---------------------------------------------------------------------- // push history base::dof::pushHistory( nucleus.getDisplacement() ); // remove the linear constraints used in the stabilisation process base::dof::clearConstraints( nucleus.getDisplacement() ); base::dof::clearConstraints( cytoSkeleton.getVelocity() ); base::dof::clearConstraints( cytoSkeleton.getPressure() ); base::dof::clearConstraints( gel.getVelocity() ); base::dof::clearConstraints( gel.getPressure() ); surfaceFeatures( boundaryMesh, membrane, envelope, surfaceQuadrature, surfaceCutQuadrature, std::cout ); std::cout << std::endl; } // end load-steps return 0; }
void tex::box_end(int box_context) { ptr p; #define LEADERS "Leaders not followed by proper glue" if (box_context < BOX_FLAG) { if (cur_box != null) { shift_amount(cur_box) = box_context; if (abs(mode) == VMODE) { append_to_vlist(cur_box); if (tex::adjust_tail != null) { if (tex::adjust_head != tex::adjust_tail) { link(tail) = link(tex::adjust_head); tail = tex::adjust_tail; } tex::adjust_tail = null; } if (mode > 0) build_page(); } else { if (abs(mode) == HMODE) { space_factor = 1000; } else { p = new_noad(); math_type(nucleus(p)) = SUB_BOX; info(nucleus(p)) = cur_box; cur_box = p; } tail_append(cur_box); } } } else if (box_context < SHIP_OUT_FLAG) { if (box_context < BOX_FLAG + 256) { reg_define(box_reg[box_context - BOX_FLAG], BOX_REG, cur_box); } else { reg_gdefine(box_reg[box_context - BOX_FLAG - 256], BOX_REG, cur_box); } } else if (cur_box != null) { if (box_context > SHIP_OUT_FLAG) { get_nbrx_token(); if (cur_cmd == HSKIP && abs(mode) != VMODE || cur_cmd == VSKIP && abs(mode) == VMODE || cur_cmd == MSKIP && abs(mode) == MMODE) { append_glue(); leader_ptr(tail) = cur_box; subtype(tail) = box_context - (LEADER_FLAG - A_LEADERS); } else { print_err(LEADERS); help_leaders(); back_error(); flush_node_list(cur_box); } } else { ship_out(cur_box); } } }
void tex::handle_right_brace () { scal d; int f; ptr p; ptr q; switch (cur_group) { case SIMPLE_GROUP: unsave(); break; case BOTTOM_LEVEL: print_err("Too many }'s"); help_close_group(); error(); break; case SEMI_SIMPLE_GROUP: case MATH_SHIFT_GROUP: case MATH_LEFT_GROUP: extra_right_brace(); break; case HBOX_GROUP: package(0); break; case ADJUSTED_HBOX_GROUP: tex::adjust_tail = tex::adjust_head; package(0); break; case VBOX_GROUP: end_graf(); package(0); break; case VTOP_GROUP: end_graf(); package(VTOP_CODE); break; case INSERT_GROUP: end_graf(); q = split_top_skip; add_glue_ref(q); d = split_max_depth; f = floating_penalty; unsave(); decr(save_ptr); p = vpack(link(head), 0, ADDITIONAL); pop_nest(); if (saved(0) < 255) { tail_append(new_node(INS_NODE_SIZE)); type(tail) = INS_NODE; subtype(tail) = saved(0); ins_height(tail) = box_height(p) + box_depth(p); ins_ptr(tail) = list_ptr(p); split_top_ptr(tail) = q; ins_depth(tail) = d; float_cost(tail) = f; } else { tail_append(new_node(SMALL_NODE_SIZE)); type(tail) = ADJUST_NODE; subtype(tail) = 0; adjust_ptr(tail) = list_ptr(p); delete_glue_ref(q); } free_node(p, BOX_NODE_SIZE); if (nest_ptr == nest) build_page(); break; case OUTPUT_GROUP: if (loc != null || (token_type != OUTPUT_TEXT && token_type != BACKED_UP)) { print_err("Unbalanced output routine"); help_output_balance(); error(); do get_token(); while (loc != null); } end_token_list(); end_graf(); unsave(); output_active = FALSE; insert_penalties = 0; if (box(255) != null) { print_err("Output routine didn't use all of "); print_esc("box255"); help_output(); box_error(255); } if (tail != head) { link(page_tail) = link(head); page_tail = tail; } if (link(page_head) != null) { if (link(contrib_head) == null) contrib_tail = page_tail; link(page_tail) = link(contrib_head); link(contrib_head) = link(page_head); link(page_head) = null; page_tail = page_head; } pop_nest(); build_page(); break; case DISC_GROUP: build_discretionary(); break; case ALIGN_GROUP: back_input(); cur_tok = sym2tok(FROZEN_CR); print_err("Missing "); print_esc("cr"); print(" inserted"); help_align_cr(); ins_error(); break; case NO_ALIGN_GROUP: end_graf(); unsave(); align_peek(); break; case VCENTER_GROUP: end_graf(); unsave(); save_ptr -= 2; p = vpackage(link(head), saved(1), saved(0), MAX_DIMEN); pop_nest(); tail_append(new_noad()); type(tail) = VCENTER_NOAD; math_type(nucleus(tail)) = SUB_BOX; info(nucleus(tail)) = p; break; case MATH_CHOICE_GROUP: build_choices(); break; case MATH_GROUP: unsave(); decr(save_ptr); math_type(saved(0)) = SUB_MLIST; p = fin_mlist(null); math_link(saved(0)) = p; if (p != null) { if (link(p) == null) { if (type(p) == ORD_NOAD) { if (math_type(subscr(p)) == EMPTY && math_type(supscr(p)) == EMPTY) { mcopy(saved(0), nucleus(p)); free_node(p, NOAD_SIZE); } } else if (type(p) == ACCENT_NOAD && saved(0) == nucleus(tail) && type(tail) == ORD_NOAD) { q = head; while (link(q) != tail) q = link(q); link(q) = p; free_node(tail, NOAD_SIZE); tail = p; } } } break; default: confusion("rightbrace"); break; } }
void tex::flush_node_list(ptr p) { ptr q; while (p != null) { q = link(p); if (is_char_node(p)) { free_avail(p); } else { switch (type(p)) { case HLIST_NODE: case VLIST_NODE: case UNSET_NODE: flush_node_list(list_ptr(p)); free_node(p, BOX_NODE_SIZE); goto done; case RULE_NODE: free_node(p, RULE_NODE_SIZE); goto done; case INS_NODE: flush_node_list(ins_ptr(p)); delete_glue_ref(split_top_ptr(p)); free_node(p, INS_NODE_SIZE); goto done; case WHATSIT_NODE: free_whatsit(p); goto done; case GLUE_NODE: fast_delete_glue_ref(glue_ptr(p)); if (leader_ptr(p) != null) flush_node_list(leader_ptr(p)); break; case KERN_NODE: case MATH_NODE: case PENALTY_NODE: break; case LIGATURE_NODE: flush_node_list(lig_ptr(p)); break; case MARK_NODE: delete_token_ref(mark_ptr(p)); break; case DISC_NODE: flush_node_list(pre_break(p)); flush_node_list(post_break(p)); break; case ADJUST_NODE: flush_node_list(adjust_ptr(p)); break; case STYLE_NODE: free_node(p, STYLE_NODE_SIZE); goto done; case CHOICE_NODE: flush_node_list(display_mlist(p)); flush_node_list(text_mlist(p)); flush_node_list(script_mlist(p)); flush_node_list(script_script_mlist(p)); free_node(p, STYLE_NODE_SIZE); goto done; case ORD_NOAD: case OP_NOAD: case BIN_NOAD: case REL_NOAD: case OPEN_NOAD: case CLOSE_NOAD: case PUNCT_NOAD: case INNER_NOAD: case RADICAL_NOAD: case OVER_NOAD: case UNDER_NOAD: case VCENTER_NOAD: case ACCENT_NOAD: if (math_type(nucleus(p)) >= SUB_BOX) flush_node_list(math_link(nucleus(p))); if (math_type(supscr(p)) >= SUB_BOX) flush_node_list(math_link(supscr(p))); if (math_type(subscr(p)) >= SUB_BOX) flush_node_list(math_link(subscr(p))); if (type(p) == RADICAL_NOAD) free_node(p, RADICAL_NOAD_SIZE); else if (type(p) == ACCENT_NOAD) free_node(p, ACCENT_NOAD_SIZE); else free_node(p, NOAD_SIZE); goto done; case LEFT_NOAD: case RIGHT_NOAD: free_node(p, NOAD_SIZE); goto done; case FRACTION_NOAD: flush_node_list(math_link(numerator(p))); flush_node_list(math_link(denominator(p))); free_node(p, FRACTION_NOAD_SIZE); goto done; default: confusion("flushing"); break; } free_node(p, SMALL_NODE_SIZE); done:; } p = q; } }
void tex::main_control() { if (every_job != null) begin_token_list(every_job, EVERY_JOB_TEXT); big_switch: get_x_token(); reswitch: if (tracing_commands > 0) show_cur_cmd_chr(); switch(abs(mode) + cur_cmd) { hmode(LETTER): hmode(OTHER_CHAR): hmode(CHAR_GIVEN): goto main_loop; hmode(CHAR_NUM): scan_char_num(); cur_chr = cur_val; goto main_loop; hmode(NO_BOUNDARY): get_x_token(); if (cur_cmd == LETTER || cur_cmd == OTHER_CHAR || cur_cmd == CHAR_GIVEN || cur_cmd == CHAR_NUM) { cancel_boundary = TRUE; } goto reswitch; hmode(SPACER): if (space_factor == 1000) { goto append_normal_space; } else { app_space(); } break; hmode(EX_SPACE): mmode(EX_SPACE): goto append_normal_space; any_mode(RELAX): vmode(SPACER): mmode(SPACER): mmode(NO_BOUNDARY): break; any_mode(IGNORE_SPACES): get_nbx_token(); goto reswitch; vmode(STOP): if (its_all_over()) return; break; any_mode(LAST_ITEM): any_mode(MAC_PARAM): non_math(EQ_NO): vmode(VMOVE): hmode(HMOVE): mmode(HMOVE): vmode(VADJUST): vmode(ITAL_CORR): report_illegal_case(); break; non_math(SUP_MARK): non_math(SUB_MARK): non_math(MATH_CHAR_NUM): non_math(MATH_GIVEN): non_math(MATH_COMP): non_math(DELIM_NUM): non_math(LEFT_RIGHT): non_math(ABOVE): non_math(RADICAL): non_math(MATH_STYLE): non_math(MATH_CHOICE): non_math(VCENTER): non_math(NON_SCRIPT): non_math(MKERN): non_math(LIMIT_SWITCH): non_math(MSKIP): non_math(MATH_ACCENT): mmode(ENDV): mmode(PAR_END): mmode(STOP): mmode(VSKIP): mmode(UN_VBOX): mmode(VALIGN): mmode(HRULE): insert_dollar_sign(); break; vmode(HRULE): hmode(VRULE): mmode(VRULE): tail_append(scan_rule_spec()); if (abs(mode) == VMODE) prev_depth = IGNORE_DEPTH; else if (abs(mode) == HMODE) space_factor = 1000; break; vmode(VSKIP): hmode(HSKIP): mmode(HSKIP): mmode(MSKIP): append_glue(); break; any_mode(KERN): mmode(MKERN): append_kern(); break; non_math(LEFT_BRACE): new_save_level(SIMPLE_GROUP); break; any_mode(BEGIN_GROUP): new_save_level(SEMI_SIMPLE_GROUP); break; any_mode(END_GROUP): if (cur_group == SEMI_SIMPLE_GROUP) { unsave(); } else { off_save(); } break; any_mode(RIGHT_BRACE): handle_right_brace(); break; vmode(HMOVE): hmode(VMOVE): mmode(VMOVE): { int t; t = cur_chr; scan_normal_dimen(); if (t == 0) { scan_box(cur_val); } else { scan_box(-cur_val); } break; } any_mode(LEADER_SHIP): scan_box(LEADER_FLAG + cur_chr - A_LEADERS); break; any_mode(MAKE_BOX): begin_box(0); break; vmode(START_PAR): new_graf(cur_chr > 0); break; vmode(LETTER): vmode(OTHER_CHAR): vmode(CHAR_NUM): vmode(CHAR_GIVEN): vmode(MATH_SHIFT): vmode(UN_HBOX): vmode(VRULE): vmode(ACCENT): vmode(DISCRETIONARY): vmode(HSKIP): vmode(VALIGN): vmode(EX_SPACE): vmode(NO_BOUNDARY): back_input(); new_graf(TRUE); break; hmode(START_PAR): mmode(START_PAR): indent_in_hmode(); break; vmode(PAR_END): normal_paragraph(); if (mode > 0) build_page(); break; hmode(PAR_END): if (align_state < 0) off_save(); end_graf(); if (mode == VMODE) build_page(); break; hmode(STOP): hmode(VSKIP): hmode(HRULE): hmode(UN_VBOX): hmode(HALIGN): head_for_vmode(); break; any_mode(INSERT): hmode(VADJUST): mmode(VADJUST): begin_insert_or_adjust(); break; any_mode(MARK): make_mark(); break; any_mode(BREAK_PENALTY): append_penalty(); break; any_mode(REMOVE_ITEM): delete_last(); break; vmode(UN_VBOX): hmode(UN_HBOX): mmode(UN_HBOX): unpackage(); break; hmode(ITAL_CORR): append_italic_correction(); break; mmode(ITAL_CORR): tail_append(new_kern(0)); break; hmode(DISCRETIONARY): mmode(DISCRETIONARY): append_discretionary(); break; hmode(ACCENT): make_accent(); break; any_mode(CAR_RET): any_mode(TAB_MARK): align_error(); break; any_mode(NO_ALIGN): no_align_error(); break; any_mode(OMIT): omit_error(); break; vmode(HALIGN): hmode(VALIGN): init_align(); break; mmode(HALIGN): if (privileged()) { if (cur_group == MATH_SHIFT_GROUP) { init_align(); } else { off_save(); } } break; vmode(ENDV): hmode(ENDV): do_endv(); break; any_mode(END_CS_NAME): cs_error(); break; hmode(MATH_SHIFT): init_math(); break; mmode(EQ_NO): if (privileged()) { if (cur_group == MATH_SHIFT_GROUP) { start_eq_no(); } else { off_save(); } } break; mmode(LEFT_BRACE): tail_append(new_noad()); back_input(); scan_math(nucleus(tail)); break; mmode(LETTER): mmode(OTHER_CHAR): mmode(CHAR_GIVEN): if (cur_chr < 256) set_math_char(math_code(cur_chr)); else set_math_char(cur_chr); break; mmode(CHAR_NUM): scan_char_num(); cur_chr = cur_val; if (cur_chr < 256) set_math_char(math_code(cur_chr)); else set_math_char(cur_chr); break; mmode(MATH_CHAR_NUM): scan_fifteen_bit_int(); set_math_char(cur_val); break; mmode(MATH_GIVEN): set_math_char(cur_chr); break; mmode(DELIM_NUM): scan_twenty_seven_bit_int(); set_math_char(cur_val / 010000); break; mmode(MATH_COMP): tail_append(new_noad()); type(tail) = cur_chr; scan_math(nucleus(tail)); break; mmode(LIMIT_SWITCH): math_limit_switch(); break; mmode(RADICAL): math_radical(); break; mmode(ACCENT): mmode(MATH_ACCENT): math_ac(); break; mmode(VCENTER): scan_spec(VCENTER_GROUP, FALSE); normal_paragraph(); push_nest(); mode = -VMODE; prev_depth = IGNORE_DEPTH; if (every_vbox != null) begin_token_list(every_vbox, EVERY_VBOX_TEXT); break; mmode(MATH_STYLE): tail_append(new_style(cur_chr)); break; mmode(NON_SCRIPT): tail_append(new_glue(zero_glue)); subtype(tail) = COND_MATH_GLUE; break; mmode(MATH_CHOICE): append_choices(); break; mmode(SUB_MARK): mmode(SUP_MARK): sub_sup(); break; mmode(ABOVE): math_fraction(); break; mmode(LEFT_RIGHT): math_left_right(); break; mmode(MATH_SHIFT): if (cur_group == MATH_SHIFT_GROUP) { after_math(); } else { off_save(); } break; any_mode(AFTER_ASSIGNMENT): get_token(); after_token = cur_tok; break; any_mode(AFTER_GROUP): get_token(); save_for_after(cur_tok); break; any_mode(IN_STREAM): clopen_stream(); break; any_mode(MESSAGE): issue_message(); break; any_mode(CASE_SHIFT): shift_case(); break; any_mode(XRAY): show_whatever(); break; any_mode(EXTENSION): do_extension(); break; default: prefixed_command(); break; } goto big_switch; #define adjust_space_factor() \ { \ main_s = sf_code(cur_chr); \ if (main_s == 1000) { \ space_factor = 1000; \ } else if (main_s < 1000) { \ if (main_s > 0) { \ space_factor = main_s; \ } \ } else if (space_factor < 1000) { \ space_factor = 1000; \ } else { \ space_factor = main_s; \ } \ } main_loop: adjust_space_factor(); main_f = cur_font; bchar = font_bchar(main_f); false_bchar = font_false_bchar(main_f); if (mode > 0 && language != clang) fix_language(); fast_new_avail(lig_stack); font(lig_stack) = main_f; character(lig_stack) = cur_l = cur_chr; cur_q = tail; if (cancel_boundary) { cancel_boundary = FALSE; main_k = NON_ADDRESS; } else { main_k = bchar_label(main_f); } if (main_k == NON_ADDRESS) goto main_loop_move_2; cur_r = cur_l; cur_l = NON_CHAR; goto main_lig_loop_1; #define pack_lig(RT_HIT) \ { \ main_p = new_ligature(main_f, cur_l, link(cur_q)); \ if (lft_hit) { \ subtype(main_p) = 2; \ lft_hit = FALSE; \ } \ if (RT_HIT && lig_stack == null) { \ incr(subtype(main_p)); \ rt_hit = FALSE; \ } \ tail = link(cur_q) = main_p; \ ligature_present = FALSE; \ } #define wrapup(RT_HIT) \ { \ if (cur_l < NON_CHAR) { \ if (character(tail) == hyphen_char(main_f) \ && link(cur_q) != null) \ ins_disc = TRUE; \ if (ligature_present) \ pack_lig(RT_HIT); \ if (ins_disc) { \ ins_disc = FALSE; \ if (mode > 0) \ tail_append(new_disc()); \ } \ } \ } main_loop_wrapup: wrapup(rt_hit); main_loop_move: if (lig_stack == null) goto reswitch; cur_q = tail; cur_l = cur_r; main_loop_move_1: if (!is_char_node(lig_stack)) goto main_loop_move_lig; main_loop_move_2: if (cur_chr < font_bc(main_f) || cur_chr > font_ec(main_f)) { char_warning(main_f, cur_chr); free_avail(lig_stack); goto big_switch; } main_i = char_info(main_f, cur_l); if (!char_exists(main_i)) { char_warning(main_f, cur_chr); free_avail(lig_stack); goto big_switch; } tail_append(lig_stack); main_loop_lookahead: get_next(); if (cur_cmd == LETTER || cur_cmd == OTHER_CHAR || cur_cmd == CHAR_GIVEN) { goto main_loop_lookahead_1; } x_token(); if (cur_cmd == LETTER || cur_cmd == OTHER_CHAR || cur_cmd == CHAR_GIVEN) { goto main_loop_lookahead_1; } if (cur_cmd == CHAR_NUM) { scan_char_num(); cur_chr = cur_val; goto main_loop_lookahead_1; } if (cur_cmd == NO_BOUNDARY) { bchar = NON_CHAR; } cur_r = bchar; lig_stack = null; goto main_lig_loop; main_loop_lookahead_1: adjust_space_factor(); fast_new_avail(lig_stack); font(lig_stack) = main_f; character(lig_stack) = cur_r = cur_chr; if (cur_r == false_bchar) { cur_r = NON_CHAR; } main_lig_loop: if (char_tag(main_i) != LIG_TAG) { goto main_loop_wrapup; } main_k = lig_kern_start(main_f, main_i); main_j = *main_k; if (skip_byte(main_j) <= STOP_FLAG) { goto main_lig_loop_2; } main_k = lig_kern_restart(main_f, main_j); main_lig_loop_1: main_j = *main_k; main_lig_loop_2: if (next_char(main_j) == cur_r && skip_byte(main_j) <= STOP_FLAG) { if (op_byte(main_j) >= KERN_FLAG) { wrapup(rt_hit); tail_append(new_kern(char_kern(main_f, main_j))); goto main_loop_move; } if (cur_l == NON_CHAR) { lft_hit = TRUE; } else if (lig_stack == null) { rt_hit = TRUE; } if(interrupted) throw std::logic_error("interrupted"); switch (op_byte(main_j)) { case 1: case 5: cur_l = rem_byte(main_j); main_i = char_info(main_f, cur_l); ligature_present = TRUE; break; case 2: case 6: cur_r = rem_byte(main_j); if (lig_stack == null) { lig_stack = new_lig_item(cur_r); bchar = NON_CHAR; } else if (is_char_node(lig_stack)) { main_p = lig_stack; lig_stack = new_lig_item(cur_r); lig_ptr(lig_stack) = main_p; } else { character(lig_stack) = cur_r; } break; case 3: cur_r = rem_byte(main_j); main_p = lig_stack; lig_stack = new_lig_item(cur_r); link(lig_stack) = main_p; break; case 7: case 11: wrapup(FALSE); cur_q = tail; cur_l = rem_byte(main_j); main_i = char_info(main_f, cur_l); ligature_present = TRUE; break; default: cur_l = rem_byte(main_j); ligature_present = TRUE; if (lig_stack == null) { goto main_loop_wrapup; } else { goto main_loop_move_1; } break; } if (op_byte(main_j) > 4 && op_byte(main_j) != 7) goto main_loop_wrapup; if (cur_l < NON_CHAR) goto main_lig_loop; main_k = bchar_label(main_f); goto main_lig_loop_1; } if (skip_byte(main_j) == 0) { incr(main_k); } else { if (skip_byte(main_j) >= STOP_FLAG) goto main_loop_wrapup; main_k += skip_byte(main_j) + 1; } goto main_lig_loop_1; main_loop_move_lig: main_p = lig_ptr(lig_stack); if (main_p != null) { tail_append(main_p); } main_t = lig_stack; lig_stack = link(main_t); free_node(main_t, SMALL_NODE_SIZE); main_i = char_info(main_f, cur_l); ligature_present = TRUE; if (lig_stack == null) { if (main_p != null) { goto main_loop_lookahead; } else { cur_r = bchar; } } else { cur_r = character(lig_stack); } goto main_lig_loop; append_normal_space: if (space_skip == zero_glue) { main_p = font_glue(cur_font); if (main_p == null) main_p = find_font_glue(cur_font); main_t = new_glue(main_p); } else { main_t = new_param_glue(SPACE_SKIP_CODE); } tail_append(main_t); goto big_switch; }