primitive_wrapper 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []