aboutsummaryrefslogtreecommitdiffstats
path: root/fsa/src/vespa/fsa/permuter.cpp
blob: 424a46409650d94c1bc294843b69fdc4b78c0f1b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * @author  Peter Boros
 * @date    2004/08/20
 * @version $Id$
 * @file    permuter.cpp
 * @brief   Permuter class.
 */

#include "permuter.h"

namespace fsa {

// {{{ Permuter::MAX_UNIT_LENGTH

const unsigned int Permuter::MAX_UNIT_LENGTH;

// }}}

// {{{ Permuter::initRec()

void Permuter::initRec(const std::string &input, std::string tail)
{
  std::string temp;
  int i;

  if(input.length()==0){
    _permtab.push_back(tail);
    _permmap[tail] = _permtab.size()-1;
  }
  else{
    for(i=input.length()-1;i>=0;i--){
      temp = input;
      temp.erase(i,1);
      initRec(temp,input.substr(i,1)+tail);
    }
  }
}

// }}}
// {{{ Permuter::Permuter()

Permuter::Permuter() : _permtab(), _permmap(), _size(0), _seed(MAX_UNIT_LENGTH,0)
{
  unsigned int i;

  _size = 1;
  for(i=1;i<=MAX_UNIT_LENGTH;i++){
    _seed[i-1]=i;
    _size*=i;
  }
  _permtab.reserve(_size);

  initRec(_seed,std::string());
}

// }}}
// {{{ Permuter::~Permuter()

Permuter::~Permuter()
{
}

// }}}
// {{{ Permuter::getPermId()

int Permuter::getPermId(const std::string &perm) const
{
  std::string t(perm);

  if(t.length()>MAX_UNIT_LENGTH)
    return -1;

  if(t.length()<MAX_UNIT_LENGTH)
    t+=_seed.substr(t.length(),MAX_UNIT_LENGTH-t.length());

  const PermMapConstIterator pi = _permmap.find(t);
  if(pi==_permmap.end())
    return -1;
  else
    return pi->second;
}

// }}}
// {{{ Permuter::firstComb()

unsigned int Permuter::firstComb(unsigned int n, unsigned int m)
{
  if(n==0 || n>31 || m==0 || m>31 || n>m)
    return 0;

  return (1<<n)-1;
}

// }}}
// {{{ Permuter::nextComb()

unsigned int Permuter::nextComb(unsigned int c, unsigned int m)

{
  if(c==0 || m==0 || m>31)
    return 0;

  unsigned int x=c;
  unsigned int limit=1<<m;
  unsigned int mask, mask1,mask2;

  if(x&1){
    mask=2;
    while(x&mask) mask<<=1;
    x^=(mask+(mask>>1));
  }
  else{
    mask=2;
    while(!(x&mask)) mask<<=1;
    mask1=mask2=0;
    while(x&mask){
      mask1<<=1;mask1++;
      mask2+=mask;
      mask<<=1;
    }
    mask1>>=1;
    x^=(mask+(mask1^mask2));
  }

  return (x<limit)?x:0;
}

// }}}

} // namespace fsa