lm 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82e0500fd99881105260a6367a282628a4c9bf5365ddc717c219fe39e1df0f19
4
- data.tar.gz: f69499c220e4a27a2a435a6820a708d458491bf0cde568d9fb9c4ddd277f13ed
3
+ metadata.gz: abf6ece1cf43b82167d54d7081335b3566d554015cb1bb2fd047fe8b1f660a9d
4
+ data.tar.gz: f87359a2ae880959e2f222040715f2cbb1f948d38423bcd8b4002252c4c0e066
5
5
  SHA512:
6
- metadata.gz: af2de852aeaf14c17783868468dd34405ccde647db085cc2fd3c1999b91c6b4aac5ec608ed9a15116049840c436979e799f7c3894608c8dd798b727e61940ba1
7
- data.tar.gz: e57c6b4f50c406ca6c1861fa9f530da28706619c3c92d1e1c9fe64e170fa195d3aec9179bfc55331afe238734d857b41a7fab8545a60a3c0cb7e24dc76307f61
6
+ metadata.gz: fab1cf7ae17461222f1522672ac5cfa59e4e435bfb38e9e80fda14ff9ac8d96c2ee31daf0c184a46efcc15392311068a22deb26b7c2fe4a1f69e3536ef46a77a
7
+ data.tar.gz: 14c83e23640306290f38f593f2474e90ee0e9690e23c592ea6792d093215fd2ab98ba77bf20c7a4e2c13119e2ab7641e066bd8f8cb4f2085ce592c6fea2562fe
data/exe/lm ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "lm"
5
+
6
+ args = ARGV[0]
7
+
8
+ if args.nil?
9
+ puts "USAGE: lm <bitpattern>"
10
+ puts "For example, to provide a bitpattern for an AND gate its 0001"
11
+ puts "The number of bits are inferred"
12
+ puts "You can use x for don't care, like lm 0xx1"
13
+ exit 1
14
+ end
15
+
16
+ min = Lm::Minimizer.new(args)
17
+ puts min.shortest.to_s(verilog: "a")
data/lib/lm/minimizer.rb CHANGED
@@ -1,6 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lm
4
+ class Degenerate
5
+ def initialize(val)
6
+ @val = val
7
+ end
8
+
9
+ def to_s(_ = nil)
10
+ @val.to_s
11
+ end
12
+ end
13
+
4
14
  class Minimizer
5
15
  def initialize(output_str)
6
16
  @output_str = output_str
@@ -11,6 +21,8 @@ module Lm
11
21
  end
12
22
 
13
23
  def canonical
24
+ return degenerate if degenerate?
25
+
14
26
  output_string.sop
15
27
  end
16
28
 
@@ -31,22 +43,52 @@ module Lm
31
43
  end
32
44
 
33
45
  def reduced_sum
34
- pos.expand.reduce
46
+ sum = pos.apply_factorize.expand
47
+ loop do
48
+ newsum = sum.reduce
49
+ return newsum if sum.to_s.length == newsum.to_s.length
50
+
51
+ sum = newsum
52
+ end
53
+ sum
35
54
  end
36
55
 
37
56
  def calculator
38
57
  String122ResultSelector.new(implicants, reduced_sum)
39
58
  end
40
59
 
60
+ def variation
61
+ @variation ||= @output_str.split("").uniq
62
+ end
63
+
64
+ # degenerate case
65
+ def degenerate?
66
+ variation.length == 1
67
+ end
68
+
69
+ def degenerate
70
+ Degenerate.new(variation.first)
71
+ end
72
+
41
73
  def shortest
74
+ return degenerate if degenerate?
75
+
42
76
  calculator.shortest
43
77
  end
44
78
 
79
+ def inputlen
80
+ output_string.bitcount
81
+ end
82
+
45
83
  def evaluate(input)
84
+ return degenerate.to_s.to_i if degenerate?
85
+
46
86
  BinFunc.new(shortest).evaluate(input)
47
87
  end
48
88
 
49
89
  def canonical_evaluate(input)
90
+ return degenerate.to_s.to_i if degenerate?
91
+
50
92
  BinFunc.new(output_string.sop).evaluate(input)
51
93
  end
52
94
  end
@@ -4,10 +4,14 @@ module Lm
4
4
  class OutputString
5
5
  def initialize(str)
6
6
  @str = str
7
+
8
+ return unless @str.length < 2
9
+
10
+ @str = @str.rjust(2, "0")
7
11
  end
8
12
 
9
13
  def bitcount
10
- Math.log(@str.length, 2).ceil
14
+ [Math.log(@str.length, 2).ceil, 1].max
11
15
  end
12
16
 
13
17
  def sop
@@ -19,6 +23,7 @@ module Lm
19
23
  prod = Product.new(bitbreak)
20
24
  res << prod
21
25
  end
26
+
22
27
  res
23
28
  end
24
29
 
data/lib/lm/petrick.rb CHANGED
@@ -67,7 +67,13 @@ module Lm
67
67
  end
68
68
 
69
69
  def string122
70
- factors.map { |sums| sums.map { |prducts| prducts.map { |x| (x.ord + 48).chr }.join("") }.join("+") }.join(",")
70
+ factors
71
+ .map do |sums|
72
+ sums.map do |prducts|
73
+ prducts.map { |x| (x.ord + 48).chr }.join("")
74
+ end.join("+")
75
+ end
76
+ .join(",")
71
77
  end
72
78
  end
73
79
  end
data/lib/lm/pos.rb CHANGED
@@ -21,7 +21,7 @@ module Lm
21
21
  @termhash ||= begin
22
22
  res = {}
23
23
  sum_array.each do |sum|
24
- terms = sum.split("+")
24
+ terms = sum.split("+", 2)
25
25
  terms.each do |term|
26
26
  res[term] ||= Set.new
27
27
  terms.each do |x|
@@ -40,13 +40,10 @@ module Lm
40
40
  seenkeys = Set.new
41
41
 
42
42
  termhash.each do |key, value|
43
- next if seenkeys.include? key
43
+ next if seenkeys.include?(([key] + value.to_a).sort.join("|").to_s)
44
44
 
45
- seenkeys << key
46
- value.each do |factor|
47
- seenkeys << factor
48
- end
49
- newarray << "#{key}+#{value.to_a.join("")}"
45
+ seenkeys << ([key] + value.to_a).sort.join("|")
46
+ newarray << "#{key}+#{value.map { |x| Sum.new(x) }.inject(:multiply)}"
50
47
  end
51
48
 
52
49
  POS.new(newarray.join(","))
data/lib/lm/sum.rb CHANGED
@@ -8,12 +8,21 @@ module Lm
8
8
  @str = str
9
9
  end
10
10
 
11
+ def multiply(other_sum)
12
+ raise "Not a sum" unless other_sum.is_a? Sum
13
+
14
+ newarr = product_list.map(&:to_a).product(other_sum.product_list.map(&:to_a))
15
+
16
+ newstr = newarr.map { |x| x.join("") }.join("+")
17
+ Sum.new(newstr)
18
+ end
19
+
11
20
  def product_list
12
21
  @str.split("+").map { |x| Set.new(x.split("")) }
13
22
  end
14
23
 
15
24
  def by_length
16
- product_list.sort(&:length)
25
+ product_list.sort_by(&:length)
17
26
  end
18
27
 
19
28
  def reduce
@@ -36,8 +45,11 @@ module Lm
36
45
  break if arr.length.zero?
37
46
  end
38
47
 
39
- res
40
48
  Sum.new(res.map { |x| x.to_a.join("") }.join("+"))
41
49
  end
50
+
51
+ def to_s
52
+ @str
53
+ end
42
54
  end
43
55
  end
data/lib/lm/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lm
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/spec/lm_spec.rb CHANGED
@@ -37,4 +37,24 @@ RSpec.describe Lm do
37
37
  min = Lm::Minimizer.new("1110")
38
38
  expect(min.canonical.to_s(verilog: "a")).to eq "~a[0] & ~a[1] | ~a[0] & a[1] | a[0] & ~a[1]"
39
39
  end
40
+
41
+ it "returns degenerate case 0" do
42
+ min = Lm::Minimizer.new("0")
43
+ expect(min.shortest.to_s(verilog: "a")).to eq "0"
44
+ end
45
+
46
+ it "returns degenerate case 00000" do
47
+ min = Lm::Minimizer.new("00000")
48
+ expect(min.shortest.to_s(verilog: "a")).to eq "0"
49
+ end
50
+
51
+ it "returns degenerate case 11" do
52
+ min = Lm::Minimizer.new("11")
53
+ expect(min.shortest.to_s(verilog: "a")).to eq "1"
54
+ end
55
+
56
+ it "returns degenerate case 1111111" do
57
+ min = Lm::Minimizer.new("1111111")
58
+ expect(min.shortest.to_s(verilog: "a")).to eq "1"
59
+ end
40
60
  end
data/spec/sum_spec.rb ADDED
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Lm::Sum do
4
+ describe "#multiply" do
5
+ it "does simple multiply" do
6
+ sop1 = Lm::Sum.new("1")
7
+ sop2 = Lm::Sum.new("2")
8
+
9
+ expect(sop1.multiply(sop2).product_list).to eq [Set.new(%w[1 2])]
10
+ end
11
+
12
+ it "does distribute multiply" do
13
+ sop1 = Lm::Sum.new("1")
14
+ sop2 = Lm::Sum.new("2+3")
15
+
16
+ expect(sop1.multiply(sop2).product_list).to eq [Set.new(%w[1 2]), Set.new(%w[1 3])]
17
+ end
18
+
19
+ it "does fully multiply" do
20
+ sop1 = Lm::Sum.new("1+4")
21
+ sop2 = Lm::Sum.new("2+3")
22
+
23
+ expect(sop1.multiply(sop2).product_list).to eq [
24
+ Set.new(%w[1 2]), Set.new(%w[1 3]),
25
+ Set.new(%w[4 2]), Set.new(%w[4 3])
26
+ ]
27
+ end
28
+
29
+ it "does fully multiply with more" do
30
+ sop1 = Lm::Sum.new("1+4")
31
+ sop2 = Lm::Sum.new("2+3+5")
32
+
33
+ expect(sop1.multiply(sop2).product_list).to eq [
34
+ Set.new(%w[1 2]), Set.new(%w[1 3]), Set.new(%w[1 5]),
35
+ Set.new(%w[4 2]), Set.new(%w[4 3]), Set.new(%w[4 5])
36
+ ]
37
+ end
38
+
39
+ it "does fully multiply inner" do
40
+ sop1 = Lm::Sum.new("1+45")
41
+ sop2 = Lm::Sum.new("2+3")
42
+
43
+ expect(sop1.multiply(sop2).product_list).to eq [
44
+ Set.new(%w[1 2]), Set.new(%w[1 3]),
45
+ Set.new(%w[4 5 2]), Set.new(%w[4 5 3])
46
+ ]
47
+ end
48
+ end
49
+
50
+ describe "#to_s" do
51
+ it "does the right thing" do
52
+ sop1 = Lm::Sum.new("1+45")
53
+ sop2 = Lm::Sum.new("2+3").multiply(sop1)
54
+ expect(sop2.to_s).to eq "21+245+31+345"
55
+ end
56
+ end
57
+ end
metadata CHANGED
@@ -1,25 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Siaw
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2022-12-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Logic Minimizer Library
14
14
  email:
15
15
  - davidsiaw@gmail.com
16
- executables: []
16
+ executables:
17
+ - lm
17
18
  extensions: []
18
19
  extra_rdoc_files: []
19
20
  files:
20
21
  - Gemfile
21
22
  - bin/console
22
23
  - bin/setup
24
+ - exe/lm
23
25
  - lib/lm.rb
24
26
  - lib/lm/bin_func.rb
25
27
  - lib/lm/implicant_chart.rb
@@ -37,6 +39,7 @@ files:
37
39
  - lm.gemspec
38
40
  - spec/lm_spec.rb
39
41
  - spec/spec_helper.rb
42
+ - spec/sum_spec.rb
40
43
  homepage: https://github.com/davidsiaw/lm
41
44
  licenses:
42
45
  - MIT
@@ -67,3 +70,4 @@ summary: Logic Minimizer
67
70
  test_files:
68
71
  - spec/lm_spec.rb
69
72
  - spec/spec_helper.rb
73
+ - spec/sum_spec.rb