+######################################################################
+# Generate a new FSM representing the concatenation of two FSMs
+######################################################################
+def fsm_concatenate(f1,f2):
+ if f1.O() > f2.I():
+ print "Not compatible FSMs\n"
+ I=f1.I()
+ S=f1.S()*f2.S()
+ O=f2.O()
+ nsm=list([0]*I*S)
+ osm=list([0]*I*S)
+ for s1 in range(f1.S()):
+ for s2 in range(f2.S()):
+ for i in range(f1.I()):
+ ns1=f1.NS()[s1*f1.I()+i]
+ o1=f1.OS()[s1*f1.I()+i]
+ ns2=f2.NS()[s2*f2.I()+o1]
+ o2=f2.OS()[s2*f2.I()+o1]
+
+ s=s1*f2.S()+s2
+ ns=ns1*f2.S()+ns2
+ nsm[s*I+i]=ns
+ osm[s*I+i]=o2
+
+
+ f=trellis.fsm(I,S,O,nsm,osm)
+ return f
+
+######################################################################
+# Generate a new FSM representing n stages through the original FSM
+######################################################################
+def fsm_radix(f,n):
+ I=f.I()**n
+ S=f.S()
+ O=f.O()**n
+ nsm=list([0]*I*S)
+ osm=list([0]*I*S)
+ for s in range(f.S()):
+ for i in range(I):
+ ii=dec2base(i,f.I(),n)
+ oo=list([0]*n)
+ ns=s
+ for k in range(n):
+ oo[k]=f.OS()[ns*f.I()+ii[k]]
+ ns=f.NS()[ns*f.I()+ii[k]]
+
+ nsm[s*I+i]=ns
+ osm[s*I+i]=base2dec(oo,f.O())
+
+
+ f=trellis.fsm(I,S,O,nsm,osm)
+ return f
+