1
2 /* Web Polygraph http://www.web-polygraph.org/
3 * Copyright 2003-2011 The Measurement Factory
4 * Licensed under the Apache License, Version 2.0 */
5
6 #include "pgl/pgl.h"
7
8 #include "xstd/Assert.h"
9 #include "pgl/PglArraySym.h"
10 #include "pgl/PglClonerSym.h"
11
12
13
14 String ClonerSym::TheType = "Cloner";
15
16 static String strContainer = "Container";
17
18
ClonerSym(const SynSym & aSource,int aCount)19 ClonerSym::ClonerSym(const SynSym &aSource, int aCount): ContainerSym(TheType),
20 theSource(aSource.clone()), theCount(aCount) {
21 Assert(theSource);
22 Assert(theCount > 0);
23 }
24
~ClonerSym()25 ClonerSym::~ClonerSym() {
26 delete theSource;
27 }
28
isA(const String & type) const29 bool ClonerSym::isA(const String &type) const {
30 if (type == TheType || ContainerSym::isA(type))
31 return true;
32
33 if (const char *p = type.str("[]"))
34 return theSource->isA(type(0, p - type.cstr()));
35
36 return false;
37 }
38
dupe(const String & type) const39 SynSym *ClonerSym::dupe(const String &type) const {
40 if (isA(type)) {
41 ClonerSym *clone = new ClonerSym(*theSource, theCount);
42 return clone;
43 }
44
45 if (const char *p = type.str("[]")) {
46 const String itemType = type(0, p - type.cstr());
47 if (theSource->canBe(itemType)) {
48 ArraySym *arr = new ArraySym(itemType);
49 arr->add(*this);
50 return arr;
51 }
52 }
53
54 return 0;
55 }
56
count() const57 int ClonerSym::count() const {
58 if (theSource->isA(strContainer))
59 return theCount*((const ContainerSym&)theSource->cast(strContainer)).count();
60 else
61 return theCount;
62 }
63
probsSet() const64 bool ClonerSym::probsSet() const {
65 if (theSource->isA(strContainer))
66 return ((const ContainerSym&)theSource->cast(strContainer)).probsSet();
67 else
68 return false;
69 }
70
itemProb(int idx,double & prob) const71 const SynSym *ClonerSym::itemProb(int idx, double &prob) const {
72 const int cnt = count();
73 Assert(cnt > 0);
74 Assert(0 <= idx && idx < cnt);
75 if (theSource->isA(strContainer)) {
76 const ContainerSym &c = (const ContainerSym&)theSource->cast(strContainer);
77 const int iOffset = idx / theCount;
78 const SynSym *i = c.itemProb(iOffset, prob);
79 prob /= theCount;
80 return i;
81 } else {
82 prob = 1.0/theCount;
83 return theSource;
84 }
85 }
86
forEach(Visitor & v,RndGen * const rng) const87 void ClonerSym::forEach(Visitor &v, RndGen *const rng) const {
88 if (theSource->isA(strContainer)) {
89 const ContainerSym &c = (const ContainerSym&)theSource->cast(strContainer);
90 for (int i = 0; i < theCount; ++i)
91 c.forEach(v, rng);
92 } else {
93 for (int i = 0; i < theCount; ++i)
94 v.visit(*theSource);
95 }
96 }
97
print(ostream & os,const String & pfx) const98 ostream &ClonerSym::print(ostream &os, const String &pfx) const {
99 return theSource->print(os, pfx) << " ** " << theCount;
100 }
101