primitive_wrapper 2.0.0 → 2.1.0

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
  SHA1:
3
- metadata.gz: de77195e3edaeb4ddf58d6e33c1fd88b26e9fc69
4
- data.tar.gz: 5c1dc0e6730a024aa6953ba29e7333185349a2ab
3
+ metadata.gz: 6aa5f4b217c6e6eddf82f17d5b062a125acbec26
4
+ data.tar.gz: e0ac33dd51b163d938c3821c0908690548529902
5
5
  SHA512:
6
- metadata.gz: 26ea44e1849e51f79624f1294131bf60f1df83274408b9375293ca3877dc56d3ce93b0d725f3587a6b62b1508fc21cae4e90e3e768da96beee1daa3697e90c46
7
- data.tar.gz: d17ed816653cc2a496279238ef5ef95cdf3ee537b464e0ef06d7ceec437f786641e7544a8f0fb3cd91aa6f78387499838c637a1f3cbdc4f8ecacdf91374b952a
6
+ metadata.gz: 047242da1920d239a5ee10d942d2246647f625f87985bd2faf78eddc34897224550f14ce020a8828e1a06f8a2f03dcf0cd09757438ab305aeeba7541b7cf1483
7
+ data.tar.gz: e824f363837b937dc44311930562a32ab05dbc8c128f7aefdfe7491f4264bc3b09f2a317ae610533fdb8bca1c20c019844c3ec20ad6c6cc739eac9ccf5193b90
data/README.md CHANGED
@@ -105,6 +105,7 @@ Hash => Property
105
105
  String => Datum
106
106
  Array => XArray
107
107
  Range => XRange
108
+ Rational => Fraction
108
109
  ```
109
110
 
110
111
  Some examples are as follows:
@@ -301,6 +302,43 @@ This works just like the other specific number wrappers previously described.
301
302
  The `Datum` container holds everything a `Number` can hold and allows `String` data to be added. This represents things that a human can type into a form as a general data thing.
302
303
  The methods of `String` are also added. Errors will occur if you try to call string methods on a `Datum` that is holding a number and visa versa.
303
304
 
305
+ #### Fraction class container
306
+
307
+ The `Fraction` container holds a `Rational` primitive. All the methods of `Rational` are mimicked with some important modifications.
308
+ All operators of `Fraction` return a `Fraction` type. Note that `Rational` types when operated with `Float` types will return `Float` types.
309
+ The mutating methods of the `Value` base class as well as some new mutating methods have also been added.
310
+ The constructor can take 1 to 3 parameters. The main idea behind this wrapper is to support mixed fractions as well as proper fractions.
311
+ See below:
312
+
313
+ ```ruby
314
+ # Construction: mixed fractions using 3 parameters
315
+ frac = Fraction.new(3,4,5) # frac.inspect == "(Fraction==>(19/5))" ... frac.to_s == "(3 4/5)" ... frac.to_s(false) == "3 4/5"
316
+ frac = Fraction(5,6,7) # shorter function call ... (Fraction==>(41/7))
317
+ frac = Fraction(-5,-6,7) # negative ... (Fraction==>(-41/7))
318
+ # note: always negate first two parameters to define negative fractions
319
+
320
+ # Construction: proper fractions using 2 parameters
321
+ frac = Fraction(27,7) # frac.inspect == "(Fraction==>(27/7))" ... frac.to_s false == "3 6/7"
322
+
323
+ # Construction: using float with/without approximation
324
+ frac = Fraction(Math::PI, 0.1) # fract.inspect == "(Fraction==>(22/7))" ... second parameter => percent error
325
+ frac = Fraction(Math::PI, 0.0001) # fract.inspect == "(Fraction==>(355/113))"
326
+ frac = Fraction(Math::PI) # fract.inspect == "(Fraction==>(884279719003555/281474976710656))"
327
+ frac = Math::PI.to_fraction(0.0001) # (Fraction==>(355/113))
328
+ frac = Math::PI.to_fraction # (Fraction==>(884279719003555/281474976710656))
329
+ # note: Rational does not have approximate construction
330
+
331
+ # mutating methods:
332
+ frac = Math::PI.to_fraction(0.0001)
333
+ frac.negate! # make negative
334
+ frac.to_s(false) # "-3 -16/113" ... note: true add parenthesis, false removes parenthesis
335
+ frac.abs! # make positive
336
+ frac.to_s(false) # "3 16/113"
337
+ frac.to_r.to_s # "355/113" ... convert to rational, then to string for proper fraction
338
+ frac *= 113 # (Fraction==>(355/1)) ... operators return type of Fraction
339
+ frac.to_s # 355 ... no parenthesis if whole number
340
+ ```
341
+
304
342
  #### SymbolW class container
305
343
 
306
344
  The `SymbolW` class container holds a `Symbol` primitive. It derives directly from `Value`.
@@ -444,7 +482,7 @@ Below is a list of what has changed:
444
482
 
445
483
  This creates a wrapped `Array` with behavior that enhances the access operators of `Array`;
446
484
  additionally a few new methods were added to the wrapped version as well as the original `Array` class.
447
- `XArray` mimics the behavior of `Array` but redefines `:[]` and `:[]=` to include lists wich comprise indexes, ranges, and arrays of indexes.
485
+ `XArray` mimics the behavior of `Array` but redefines `:[]` and `:[]=` to include lists which comprise indexes, ranges, and arrays of indexes.
448
486
  There is also behavior that defines many-to-one, one-to-many, and many-to-many operations. Note that one-to-one behavior has not changed.
449
487
  An example best explains how this works:
450
488
 
@@ -574,21 +612,25 @@ This can be mostly a matter of taste, but we can choose custom names that convey
574
612
  So it is left to you to decide.
575
613
 
576
614
  ## Revision History
615
+
616
+ ### Version 2.1.0
617
+ * Added Fraction wrapper for Rational types
618
+
577
619
  ### Version 2.0.0
578
- * fixed Range reversals defined with excluded end
579
- * added #type to Object, Value
580
- * added #simple? to Range, XRange
620
+ * Fixed Range reversals defined with excluded end
621
+ * Added #type to Object, Value
622
+ * Added #simple? to Range, XRange
581
623
 
582
624
  ### Version 1.0.1
583
- * updated documentation to include undocumented methods
584
- * fixed XArray `#delete_at` bugs
625
+ * Updated documentation to include undocumented methods
626
+ * Fixed XArray `#delete_at` bugs
585
627
 
586
628
  ### Version 1.0.0
587
- * fixed wrapper inside wrapper causing stack overflow
629
+ * Fixed wrapper inside wrapper causing stack overflow
588
630
  * Documentation updates
589
631
  * Added new wrappers for Range, Array as XRange and XArray
590
- * added primitive methods
591
- * added Value methods, and enhanced other derived wrappers
632
+ * Added primitive methods
633
+ * Added Value methods, and enhanced other derived wrappers
592
634
 
593
635
  ## Development
594
636
 
@@ -34,6 +34,7 @@ class Object
34
34
  return Property.new(self) if self.kind_of? Hash
35
35
  return XArray.new(self) if self.kind_of? Array
36
36
  return XRange.new(self) if self.kind_of? Range
37
+ return Fraction.new(self) if self.kind_of? Rational
37
38
  return Value.new(self)
38
39
  end
39
40
  end
@@ -717,6 +718,166 @@ class Property < Value
717
718
  end
718
719
  end
719
720
 
721
+ class Fraction < ValueAdd
722
+ capture_base_methods(Rational)
723
+
724
+ def coerce(other)
725
+ [Fraction.new(other.prim_value), self.prim_value]
726
+ end
727
+
728
+ def self.approximate_by_float(p1, pcnt=nil)
729
+ return Fraction.new(p1.prim_value) if pcnt.nil?
730
+ pcnt/= 100.0
731
+ neg = p1.negative?
732
+ p1=p1.abs
733
+ if p1 >=1.0
734
+ top = p1.floor
735
+ bot = 1
736
+ else
737
+ top = 1
738
+ bot = (1/p1).floor
739
+ end
740
+ loop do
741
+ app = top.to_f/bot.to_f
742
+ tst = (app - p1).abs/p1
743
+ break if tst < pcnt
744
+ if app > p1
745
+ bot += 1
746
+ else
747
+ top += 1
748
+ end
749
+ end
750
+ return Fraction.new(top.prim_value,bot.prim_value)
751
+ end
752
+
753
+ def initialize(*prms)
754
+ #obj = obj.prim_value
755
+ #ensure_valid(obj)
756
+ #@value = obj
757
+ if 1==prms.count
758
+ @value = Rational(prms[0].prim_value)
759
+ elsif 2==prms.count
760
+ if prms[0].type_of? Float
761
+ fract = self.class.approximate_by_float(prms[0].prim_value,prms[1].prim_value)
762
+ @value = fract.prim_value
763
+ else
764
+ @value = Rational(prms[0].prim_value,prms[1].prim_value)
765
+ end
766
+
767
+ elsif 3==prms.count
768
+ @value = Rational(prms[1].prim_value,prms[2].prim_value) + prms[0].prim_value
769
+ else
770
+ raise("expected 1..3 parameters")
771
+ end
772
+ end
773
+
774
+ def replace(other)
775
+ @value = Rational(other.prim_value)
776
+ end
777
+
778
+ def abs!
779
+ @value = @value.abs
780
+ self
781
+ end
782
+
783
+ def negate!
784
+ @value = -@value.abs
785
+ self
786
+ end
787
+
788
+ def +(other)
789
+ Fraction.new(@value + other)
790
+ end
791
+
792
+ def -(other)
793
+ Fraction.new(@value - other)
794
+ end
795
+
796
+ def *(other)
797
+ Fraction.new(@value * other)
798
+ end
799
+
800
+ def **(other)
801
+ Fraction.new(@value ** other)
802
+ end
803
+
804
+ def %(other)
805
+ Fraction.new(@value % other)
806
+ end
807
+
808
+ def /(other)
809
+ Fraction.new(@value / other)
810
+ end
811
+
812
+ def +@
813
+ Fraction.new(@value)
814
+ end
815
+
816
+ def -@
817
+ Fraction.new(-@value)
818
+ end
819
+
820
+ def to_fraction
821
+ self
822
+ end
823
+
824
+ def to_s(paren=true)
825
+ return @value.numerator if @value.denominator==1
826
+ if @value.numerator.abs < @value.denominator
827
+ if paren
828
+ return "(#{@value.numerator}/#{@value.denominator})"
829
+ else
830
+ return "#{@value.numerator}/#{@value.denominator}"
831
+ end
832
+ end
833
+ if @value.negative?
834
+ rat = -@value
835
+ whole, rem = rat.numerator.divmod rat.denominator
836
+ if paren
837
+ return "(-#{whole} -#{rem}/#{@value.denominator})"
838
+ else
839
+ return "-#{whole} -#{rem}/#{@value.denominator}"
840
+ end
841
+
842
+ end
843
+ whole, rem = @value.numerator.divmod @value.denominator
844
+ if paren
845
+ return "(#{whole} #{rem}/#{@value.denominator})"
846
+ else
847
+ return "#{whole} #{rem}/#{@value.denominator}"
848
+ end
849
+ end
850
+
851
+ def valid_type(prm)
852
+ return true
853
+ end
854
+
855
+ end
856
+
857
+ module Kernel
858
+ def Fraction(*prms)
859
+ Fraction.new(*prms)
860
+ end
861
+ end
862
+
863
+ class Integer
864
+ def to_fraction
865
+ Fraction.new(self)
866
+ end
867
+ end
868
+
869
+ class Float
870
+ def to_fraction(pcnt=nil)
871
+ Fraction.approximate_by_float(self, pcnt)
872
+ end
873
+ end
874
+
875
+ class Rational
876
+ def to_fraction
877
+ Fraction.new(self)
878
+ end
879
+ end
880
+
720
881
  class XRange < ValueAdd
721
882
  capture_base_methods(Range)
722
883
  def valid_type(prm)
@@ -2,6 +2,8 @@
2
2
  # note that there is no exclude start, so reversing will require recalculation or simplification
3
3
  # ... put this on the back burner for now
4
4
 
5
+ # adding rational to fraction
6
+
5
7
  module PrimitiveWrapper
6
- VERSION = "2.0.0"
8
+ VERSION = "2.1.0"
7
9
  end
@@ -20,7 +20,8 @@ What is interesting to note is Number objects do not derive from `Numeric`, but
20
20
  but at the same time, `Number` objects mimic the methods of `Fixnum`, `Complex`, `Float`, etc.
21
21
  Many of the wrappers can be used in an expression without having to call an access method.
22
22
  There are also new types: `Bool` which wraps `true,false` and `Property` which wraps `Hash` types.
23
- The `Property` object auto-methodizes the key names of the Hash.}
23
+ The `Property` object auto-methodizes the key names of the Hash.
24
+ Also `Fraction` supports mixed fractions.}
24
25
 
25
26
  spec.license = "MIT"
26
27
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primitive_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Colvin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-20 00:00:00.000000000 Z
11
+ date: 2018-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: blockify
@@ -144,6 +144,7 @@ description: |-
144
144
  Many of the wrappers can be used in an expression without having to call an access method.
145
145
  There are also new types: `Bool` which wraps `true,false` and `Property` which wraps `Hash` types.
146
146
  The `Property` object auto-methodizes the key names of the Hash.
147
+ Also `Fraction` supports mixed fractions.
147
148
  email:
148
149
  - bryan@bdlsys.com
149
150
  executables: []