Browse Source

Add methods to Number

Add the following methods inspired by Pharo implementation:

* Number>>degreesToRadians
* Number>>radiansToDegrees
* Number>>min:max:
Steven Rémot 6 years ago
parent
commit
4dfbe9fa97
4 changed files with 288 additions and 4 deletions
  1. 123 0
      src/Kernel-Objects.js
  2. 20 0
      src/Kernel-Objects.st
  3. 126 3
      src/Kernel-Tests.js
  4. 19 1
      src/Kernel-Tests.st

+ 123 - 0
src/Kernel-Objects.js

@@ -3750,6 +3750,37 @@ messageSends: ["+", "truncated", "*", "next", "new"]
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "between:and:",
+protocol: "testing",
+fn: function(min,max){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self.__gt_eq(min))._and_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $self.__lt_eq(max);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"between:and:",{min:min,max:max},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["min", "max"],
+source: "between: min and: max\x0a ^ self >= min and: [ self <= max ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["and:", ">=", "<="]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "ceiling",
@@ -3839,6 +3870,29 @@ messageSends: ["copy"]
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "degreesToRadians",
+protocol: "converting",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self.__star($recv($globals.Number)._radiansPerDegree());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"degreesToRadians",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "degreesToRadians\x0a\x09^ self * Number radiansPerDegree",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["*", "radiansPerDegree"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "even",
@@ -4065,6 +4119,29 @@ messageSends: []
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "min:max:",
+protocol: "arithmetic",
+fn: function(aMin,aMax){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._min_(aMin))._max_(aMax);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"min:max:",{aMin:aMin,aMax:aMax},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aMin", "aMax"],
+source: "min: aMin max: aMax\x0a\x09^ (self min: aMin) max: aMax",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["max:", "min:"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "negated",
@@ -4205,6 +4282,29 @@ messageSends: []
 }),
 $globals.Number);
 
+$core.addMethod(
+$core.method({
+selector: "radiansToDegrees",
+protocol: "converting",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $self.__slash($recv($globals.Number)._radiansPerDegree());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"radiansToDegrees",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "radiansToDegrees\x0a\x09^ self / Number radiansPerDegree",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["/", "radiansPerDegree"]
+}),
+$globals.Number);
+
 $core.addMethod(
 $core.method({
 selector: "raisedTo:",
@@ -4815,6 +4915,29 @@ messageSends: []
 }),
 $globals.Number.a$cls);
 
+$core.addMethod(
+$core.method({
+selector: "radiansPerDegree",
+protocol: "instance creation",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._pi()).__slash((180));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"radiansPerDegree",{},$globals.Number.a$cls)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "radiansPerDegree\x0a\x09^ (self pi) / 180",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["/", "pi"]
+}),
+$globals.Number.a$cls);
+
 
 $core.addClass("Point", $globals.Object, ["x", "y"], "Kernel-Objects");
 //>>excludeStart("ide", pragmas.excludeIdeData);

+ 20 - 0
src/Kernel-Objects.st

@@ -816,6 +816,10 @@ min: aNumber
 	<inlineJS: 'return Math.min(self, aNumber);'>
 !
 
+min: aMin max: aMax
+	^ (self min: aMin) max: aMax
+!
+
 negated
 	^ 0 - self
 ! !
@@ -888,10 +892,18 @@ ceiling
 	<inlineJS: 'return Math.ceil(self);'>
 !
 
+degreesToRadians
+	^ self * Number radiansPerDegree
+!
+
 floor
 	<inlineJS: 'return Math.floor(self);'>
 !
 
+radiansToDegrees
+	^ self / Number radiansPerDegree
+!
+
 rounded
 	<inlineJS: 'return Math.round(self);'>
 !
@@ -1058,6 +1070,10 @@ printShowingDecimalPlaces: placesDesired
 
 !Number methodsFor: 'testing'!
 
+between: min and: max
+ ^ self >= min and: [ self <= max ]
+!
+
 even
 	^ 0 = (self \\ 2)
 !
@@ -1108,6 +1124,10 @@ e
 
 pi
 	<inlineJS: 'return Math.PI'>
+!
+
+radiansPerDegree
+	^ (self pi) / 180
 ! !
 
 Object subclass: #Point

+ 126 - 3
src/Kernel-Tests.js

@@ -12211,6 +12211,60 @@ messageSends: ["assert:equals:", "asNumber"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testBetweenAnd",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$3,$2,$5,$4;
+$1=(4)._between_and_((3),(5));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($1);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=1;
+//>>excludeEnd("ctx");
+$3=(1)._between_and_((5),(6));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=2;
+//>>excludeEnd("ctx");
+$2=$recv($3)._not();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["not"]=1;
+//>>excludeEnd("ctx");
+$self._assert_($2);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=2;
+//>>excludeEnd("ctx");
+$5=(90)._between_and_((67),(87));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["between:and:"]=3;
+//>>excludeEnd("ctx");
+$4=$recv($5)._not();
+$self._assert_($4);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:"]=3;
+//>>excludeEnd("ctx");
+$self._assert_((1)._between_and_((1),(1)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testBetweenAnd",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testBetweenAnd\x0a\x09self assert: (4 between: 3 and: 5).\x0a\x09self assert: (1 between: 5 and: 6) not.\x0a\x09self assert: (90 between: 67 and: 87) not.\x0a\x09self assert: (1 between: 1 and: 1).",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "between:and:", "not"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testCeiling",
@@ -12351,6 +12405,30 @@ messageSends: ["assert:", "==", "copy", "deepCopy"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testDegreesToRadians",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._assert_($recv($recv($recv((180)._degreesToRadians()).__minus($recv($globals.Number)._pi()))._abs()).__lt_eq((0.01)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testDegreesToRadians",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testDegreesToRadians\x0a\x09self assert: (180 degreesToRadians - Number pi) abs <= 0.01.",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "<=", "abs", "-", "degreesToRadians", "pi"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testEquality",
@@ -13197,16 +13275,37 @@ $core.addMethod(
 $core.method({
 selector: "testMinMax",
 protocol: "tests",
-fn: function (){
+fn: function(){
 var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
+var $1,$2;
 $self._assert_equals_((2)._max_((5)),(5));
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["assert:equals:"]=1;
 //>>excludeEnd("ctx");
 $self._assert_equals_((2)._min_((5)),(2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=2;
+//>>excludeEnd("ctx");
+$1=(2)._min_max_((5),(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["min:max:"]=1;
+//>>excludeEnd("ctx");
+$self._assert_equals_($1,(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=3;
+//>>excludeEnd("ctx");
+$2=(7)._min_max_((5),(3));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["min:max:"]=2;
+//>>excludeEnd("ctx");
+$self._assert_equals_($2,(5));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["assert:equals:"]=4;
+//>>excludeEnd("ctx");
+$self._assert_equals_((4)._min_max_((5),(3)),(4));
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testMinMax",{},$globals.NumberTest)});
@@ -13214,10 +13313,10 @@ return self;
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
-source: "testMinMax\x0a\x09\x0a\x09self assert: (2 max: 5) equals: 5.\x0a\x09self assert: (2 min: 5) equals: 2",
+source: "testMinMax\x0a\x09\x0a\x09self assert: (2 max: 5) equals: 5.\x0a\x09self assert: (2 min: 5) equals: 2.\x0a\x09self assert: (2 min: 5 max: 3) equals: 3.\x0a\x09self assert: (7 min: 5 max: 3) equals: 5.\x0a\x09self assert: (4 min: 5 max: 3) equals: 4.",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["assert:equals:", "max:", "min:"]
+messageSends: ["assert:equals:", "max:", "min:", "min:max:"]
 }),
 $globals.NumberTest);
 
@@ -13387,6 +13486,30 @@ messageSends: ["assert:equals:", "printShowingDecimalPlaces:", "negated"]
 }),
 $globals.NumberTest);
 
+$core.addMethod(
+$core.method({
+selector: "testRadiansToDegrees",
+protocol: "tests",
+fn: function(){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._assert_($recv($recv($recv($recv($recv($globals.Number)._pi())._radiansToDegrees()).__minus((180)))._abs()).__lt_eq((0.01)));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testRadiansToDegrees",{},$globals.NumberTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testRadiansToDegrees\x0a\x09self assert: (Number pi radiansToDegrees - 180) abs <= 0.01.",
+referencedClasses: ["Number"],
+//>>excludeEnd("ide");
+messageSends: ["assert:", "<=", "abs", "-", "radiansToDegrees", "pi"]
+}),
+$globals.NumberTest);
+
 $core.addMethod(
 $core.method({
 selector: "testRaisedTo",

+ 19 - 1
src/Kernel-Tests.st

@@ -2271,6 +2271,13 @@ testAsNumber
 	self assert: 3 asNumber equals: 3.
 !
 
+testBetweenAnd
+	self assert: (4 between: 3 and: 5).
+	self assert: (1 between: 5 and: 6) not.
+	self assert: (90 between: 67 and: 87) not.
+	self assert: (1 between: 1 and: 1).
+!
+
 testCeiling
 	self assert: 1.2 ceiling equals: 2.
 	self assert: -1.2 ceiling equals: -1.
@@ -2296,6 +2303,10 @@ testCopying
 	self assert: 1 deepCopy == 1
 !
 
+testDegreesToRadians
+	self assert: (180 degreesToRadians - Number pi) abs <= 0.01.
+!
+
 testEquality
 	self assert: (1 = 1).
 	self assert: (0 = 0).
@@ -2394,7 +2405,10 @@ testLog
 testMinMax
 	
 	self assert: (2 max: 5) equals: 5.
-	self assert: (2 min: 5) equals: 2
+	self assert: (2 min: 5) equals: 2.
+	self assert: (2 min: 5 max: 3) equals: 3.
+	self assert: (7 min: 5 max: 3) equals: 5.
+	self assert: (4 min: 5 max: 3) equals: 4.
 !
 
 testNegated
@@ -2418,6 +2432,10 @@ testPrintShowingDecimalPlaces
 	self assert: (0 printShowingDecimalPlaces: 2) equals: '0.00'.
 !
 
+testRadiansToDegrees
+	self assert: (Number pi radiansToDegrees - 180) abs <= 0.01.
+!
+
 testRaisedTo
 	self assert: (2 raisedTo: 4) equals: 16.
 	self assert: (2 raisedTo: 0) equals: 1.