diff options
Diffstat (limited to 'gfsm/gfsm/src/libgfsm/gfsmArith.c')
-rw-r--r-- | gfsm/gfsm/src/libgfsm/gfsmArith.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/gfsm/gfsm/src/libgfsm/gfsmArith.c b/gfsm/gfsm/src/libgfsm/gfsmArith.c new file mode 100644 index 0000000..f9ccf11 --- /dev/null +++ b/gfsm/gfsm/src/libgfsm/gfsmArith.c @@ -0,0 +1,199 @@ +/*=============================================================================*\ + * File: gfsmArith.c + * Author: Bryan Jurish <moocow@ling.uni-potsdam.de> + * Description: finite state machine library + * + * Copyright (c) 2005-2007 Bryan Jurish. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + *=============================================================================*/ + +#include <math.h> +#include <glib.h> +#include <gfsmArith.h> +#include <gfsmArcIter.h> + + +/*====================================================================== + * Methods: arithmetic: Generic + */ + +//-------------------------------------------------------------- +gfsmAutomaton *gfsm_automaton_arith(gfsmAutomaton *fsm, + gfsmArithOp op, + gfsmWeight arg, + gfsmLabelVal lo, + gfsmLabelVal hi, + gboolean do_arcs, + gboolean do_final, + gboolean do_zero) +{ + if (op == gfsmAONone) return fsm; //-- dummy operation + + //-- arc weights + if (do_arcs) { + gfsmStateId qid; + + if (fsm->flags.sort_mode == gfsmASMWeight) + fsm->flags.sort_mode = gfsmASMNone; //-- arc-weights may be destructively altered + + for (qid=0; qid < fsm->states->len; qid++) { + gfsmArcIter ai; + for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_both(&ai,lo,hi); + gfsm_arciter_ok(&ai); + gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi)) + { + gfsmArc *arc = gfsm_arciter_arc(&ai); + arc->weight = gfsm_weight_arith(fsm->sr, op, arc->weight, arg, do_zero); + } + } + } + + //-- final weights + if (do_final) gfsm_automaton_arith_final(fsm, op, arg, do_zero); + + return fsm; +} + +//-------------------------------------------------------------- +gfsmAutomaton *gfsm_automaton_arith_state(gfsmAutomaton *fsm, + gfsmStateId qid, + gfsmArithOp op, + gfsmWeight arg, + gfsmLabelVal lo, + gfsmLabelVal hi, + gboolean do_arcs, + gboolean do_final, + gboolean do_zero) +{ + if (qid==gfsmNoState) return gfsm_automaton_arith(fsm,op,arg,lo,hi,do_arcs,do_final,do_zero); + + //-- arc weights + if (do_arcs) { + gfsmArcIter ai; + + if (fsm->flags.sort_mode == gfsmASMWeight) + fsm->flags.sort_mode = gfsmASMNone; //-- arc-weights may be destructively altered + + for (gfsm_arciter_open(&ai,fsm,qid), gfsm_arciter_seek_both(&ai,lo,hi); + gfsm_arciter_ok(&ai); + gfsm_arciter_next(&ai), gfsm_arciter_seek_both(&ai,lo,hi)) + { + gfsmArc *arc = gfsm_arciter_arc(&ai); + arc->weight = gfsm_weight_arith(fsm->sr, op, arc->weight, arg, do_zero); + } + } + + //-- final weight + if (do_final) { + gfsm_automaton_set_final_state_full(fsm, + qid, + gfsm_automaton_is_final_state(fsm, qid), + gfsm_weight_arith(fsm->sr, + op, + gfsm_automaton_get_final_weight(fsm, qid), + arg, + do_zero)); + } + + return fsm; +} + +//-------------------------------------------------------------- +gfsmWeight gfsm_weight_arith(gfsmSemiring *sr, + gfsmArithOp op, + gfsmWeight w1, + gfsmWeight w2, + gboolean do_zero) +{ + if (!do_zero && w1==sr->zero) return w1; + + switch (op) { + + case gfsmAOExp: ///< Exponentiate + return expf(w1); + break; + + case gfsmAOLog: ///< Logarithm + return logf(w1); + break; + + case gfsmAONoNeg: ///< Real force-positive + return (w1 < 0 ? (-w1) : w1); + break; + + case gfsmAOAdd: ///< Real Addition + return w1+w2; + break; + + case gfsmAOMult: ///< Real Multiplication + return w1*w2; + break; + + case gfsmAOSRNoNeg: ///< Semiring Force positive + return (gfsm_sr_less(sr,sr->zero,w1) ? sr->zero : w1); + break; + + case gfsmAOSRPlus: ///< Semiring Addition + return gfsm_sr_plus(sr,w1,w2); + break; + + case gfsmAOSRTimes: ///< Semiring Multiplication + return gfsm_sr_times(sr,w1,w2); + break; + + case gfsmAONone: ///< No operation + default: + return w1; + } + return w1; //-- should never happen +} + + + +/*====================================================================== + * Methods: arithmetic: final + */ + +//-------------------------------------------------------------- +gboolean _gfsm_automaton_arith_final_foreach_func(gfsmStateId id, + gpointer pw, + gfsmArithParams *params) +{ + gfsmWeight w = gfsm_ptr2weight(pw); + gfsm_weightmap_insert(params->fsm->finals, + GUINT_TO_POINTER(id), + gfsm_weight_arith(params->fsm->sr, + params->op, + w, + params->arg, + params->do_zero)); + return FALSE; +} + + +//-------------------------------------------------------------- +gfsmAutomaton *gfsm_automaton_arith_final(gfsmAutomaton *fsm, + gfsmArithOp op, + gfsmWeight arg, + gboolean do_zero) +{ + gfsmArithParams params = { fsm, op, arg, do_zero }; + g_tree_foreach(fsm->finals, + (GTraverseFunc)_gfsm_automaton_arith_final_foreach_func, + ¶ms); + return fsm; +} + |