Add Code 93 support. Update tests to reflect new (better) number of successes.
[zxing.git] / core / src / com / google / zxing / oned / rss / RSSUtils.java
1 /*
2  * Copyright 2009 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.oned.rss;
18
19 /** Adapted from listings in ISO/IEC 24724 Appendix B and Appendix G. */
20 public final class RSSUtils {
21
22   private RSSUtils() {}
23
24   static int[] getRSSwidths(int val, int n, int elements, int maxWidth, boolean noNarrow) {
25     int[] widths = new int[elements];
26     int bar;
27     int narrowMask = 0;
28     for (bar = 0; bar < elements - 1; bar++) {
29       narrowMask |= (1 << bar);
30       int elmWidth = 1;
31       int subVal;
32       while (true) {
33         subVal = combins(n - elmWidth - 1, elements - bar - 2);
34         if (noNarrow && (narrowMask == 0) &&
35             (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {
36           subVal -= combins(n - elmWidth - (elements - bar), elements - bar - 2);
37         }
38         if (elements - bar - 1 > 1) {
39           int lessVal = 0;
40           for (int mxwElement = n - elmWidth - (elements - bar - 2);
41                mxwElement > maxWidth;
42                mxwElement--) {
43             lessVal += combins(n - elmWidth - mxwElement - 1, elements - bar - 3);
44           }
45           subVal -= lessVal * (elements - 1 - bar);
46         } else if (n - elmWidth > maxWidth) {
47           subVal--;
48         }
49         val -= subVal;
50         if (val < 0) {
51           break;
52         }
53         elmWidth++;
54         narrowMask &= ~(1 << bar);
55       }
56       val += subVal;
57       n -= elmWidth;
58       widths[bar] = elmWidth;
59     }
60     widths[bar] = n;
61     return widths;
62   }
63
64   public static int getRSSvalue(int[] widths, int maxWidth, boolean noNarrow) {
65     int elements = widths.length;
66     int n = 0;
67     for (int i = 0; i < elements; i++) {
68       n += widths[i];
69     }
70     int val = 0;
71     int narrowMask = 0;
72     for (int bar = 0; bar < elements - 1; bar++) {
73       int elmWidth;
74       for (elmWidth = 1, narrowMask |= (1 << bar);
75            elmWidth < widths[bar];
76            elmWidth++, narrowMask &= ~(1 << bar)) {
77         int subVal = combins(n - elmWidth - 1, elements - bar - 2);
78         if (noNarrow && (narrowMask == 0) &&
79             (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) {
80           subVal -= combins(n - elmWidth - (elements - bar),
81                             elements - bar - 2);
82         }
83         if (elements - bar - 1 > 1) {
84           int lessVal = 0;
85           for (int mxwElement = n - elmWidth - (elements - bar - 2);
86                mxwElement > maxWidth; mxwElement--) {
87             lessVal += combins(n - elmWidth - mxwElement - 1,
88                                elements - bar - 3);
89           }
90           subVal -= lessVal * (elements - 1 - bar);
91         } else if (n - elmWidth > maxWidth) {
92           subVal--;
93         }
94         val += subVal;
95       }
96       n -= elmWidth;
97     }
98     return (val);
99   }
100
101   static int combins(int n, int r) {
102     int maxDenom, minDenom;
103     if (n - r > r) {
104       minDenom = r;
105       maxDenom = n - r;
106     } else {
107       minDenom = n - r;
108       maxDenom = r;
109     }
110     int val = 1;
111     int j = 1;
112     for (int i = n; i > maxDenom; i--) {
113       val *= i;
114       if (j <= minDenom) {
115         val /= j;
116         j++;
117       }
118     }
119     while (j <= minDenom) {
120       val /= j;
121       j++;
122     }
123     return (val);
124   }
125
126   static int[] elements(int[] eDist, int N, int K) {
127     int[] widths = new int[eDist.length + 2];
128     int twoK = K << 1;
129     widths[0] = 1;
130     int i;
131     int minEven = 10;
132     int barSum = 1;
133     for (i = 1; i < twoK - 2; i += 2) {
134       widths[i] = eDist[i - 1] - widths[i - 1];
135       widths[i + 1] = eDist[i] - widths[i];
136       barSum += widths[i] + widths[i + 1];
137       if (widths[i] < minEven) {
138         minEven = widths[i];
139       }
140     }
141     widths[twoK - 1] = N - barSum;
142     if (widths[twoK - 1] < minEven) {
143       minEven = widths[twoK - 1];
144     }
145     if (minEven > 1) {
146       for (i = 0; i < twoK; i += 2) {
147         widths[i] += minEven - 1;
148         widths[i + 1] -= minEven - 1;
149       }
150     }
151     return widths;
152   }
153
154
155 }