Browse Source

Merge pull request #688 from matthias-springer/number-mathematical

Add more mathematical functions to Number
Nicolas Petton 10 years ago
parent
commit
b10b1b1882
4 changed files with 422 additions and 10 deletions
  1. 240 2
      js/Kernel-Objects.js
  2. 82 2
      js/Kernel-Tests.js
  3. 68 6
      st/Kernel-Objects.st
  4. 32 0
      st/Kernel-Tests.st

+ 240 - 2
js/Kernel-Objects.js

@@ -2229,6 +2229,24 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "**",
+category: 'mathematical functions',
+fn: function (exponent){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self._raisedTo_(exponent);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"**",{exponent:exponent},smalltalk.Number)})},
+args: ["exponent"],
+source: "** exponent\x0a\x09^self raisedTo: exponent",
+messageSends: ["raisedTo:"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "+",
@@ -2277,6 +2295,24 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "//",
+category: 'arithmetic',
+fn: function (aNumber){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self.__slash(aNumber))._floor();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"//",{aNumber:aNumber},smalltalk.Number)})},
+args: ["aNumber"],
+source: "// aNumber\x0a\x09^(self / aNumber) floor",
+messageSends: ["floor", "/"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "<",
@@ -2413,6 +2449,54 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcCos",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.acos(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcCos",{},smalltalk.Number)})},
+args: [],
+source: "arcCos\x0a\x09<return Math.acos(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcSin",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.asin(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcSin",{},smalltalk.Number)})},
+args: [],
+source: "arcSin\x0a\x09<return Math.asin(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcTan",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.atan(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcTan",{},smalltalk.Number)})},
+args: [],
+source: "arcTan\x0a\x09<return Math.atan(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "asJSON",
@@ -2555,6 +2639,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cos",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.cos(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"cos",{},smalltalk.Number)})},
+args: [],
+source: "cos\x0a\x09<return Math.cos(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "deepCopy",
@@ -2675,6 +2775,54 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "ln",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"ln",{},smalltalk.Number)})},
+args: [],
+source: "ln\x0a\x09<return Math.log(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "log",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self) / Math.LN10;;
+return self}, function($ctx1) {$ctx1.fill(self,"log",{},smalltalk.Number)})},
+args: [],
+source: "log\x0a\x09<return Math.log(self) / Math.LN10;>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "log:",
+category: 'mathematical functions',
+fn: function (aNumber){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self) / Math.log(aNumber);;
+return self}, function($ctx1) {$ctx1.fill(self,"log:",{aNumber:aNumber},smalltalk.Number)})},
+args: ["aNumber"],
+source: "log: aNumber\x0a\x09<return Math.log(self) / Math.log(aNumber);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "max:",
@@ -2811,6 +2959,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "raisedTo:",
+category: 'mathematical functions',
+fn: function (exponent){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.pow(self, exponent);;
+return self}, function($ctx1) {$ctx1.fill(self,"raisedTo:",{exponent:exponent},smalltalk.Number)})},
+args: ["exponent"],
+source: "raisedTo: exponent\x0a\x09<return Math.pow(self, exponent);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "rounded",
@@ -2827,10 +2991,52 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "sign",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self._isZero();
+if(smalltalk.assert($1)){
+return (0);
+};
+$2=self._positive();
+if(smalltalk.assert($2)){
+return (1);
+} else {
+return (-1);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"sign",{},smalltalk.Number)})},
+args: [],
+source: "sign\x0a\x09self isZero \x0a\x09\x09ifTrue: [ ^ 0 ].\x0a\x09self positive\x0a\x09\x09ifTrue: [ ^ 1 ]\x0a\x09\x09ifFalse: [ ^ -1 ].",
+messageSends: ["ifTrue:", "isZero", "ifTrue:ifFalse:", "positive"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "sin",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.sin(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"sin",{},smalltalk.Number)})},
+args: [],
+source: "sin\x0a\x09<return Math.sin(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "sqrt",
-category: 'arithmetic',
+category: 'mathematical functions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -2846,7 +3052,7 @@ smalltalk.Number);
 smalltalk.addMethod(
 smalltalk.method({
 selector: "squared",
-category: 'arithmetic',
+category: 'mathematical functions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -2861,6 +3067,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tan",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.tan(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"tan",{},smalltalk.Number)})},
+args: [],
+source: "tan\x0a\x09<return Math.tan(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "timesRepeat:",
@@ -3081,6 +3303,22 @@ referencedClasses: []
 smalltalk.Number);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "e",
+category: 'instance creation',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.E;;
+return self}, function($ctx1) {$ctx1.fill(self,"e",{},smalltalk.Number.klass)})},
+args: [],
+source: "e\x0a\x09<return Math.E;>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number.klass);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "heliosClass",

+ 82 - 2
js/Kernel-Tests.js

@@ -3458,12 +3458,14 @@ self._assert_equals_((2).__minus((1)),(1));
 self._assert_equals_((-2).__minus((1)),(-3));
 self._assert_equals_((12).__slash((2)),(6));
 self._assert_equals_((3).__star((4)),(12));
+self._assert_equals_((7).__slash_slash((2)),(3));
+self._assert_equals_((7).__backslash_backslash((2)),(1));
 self._assert_equals_(_st((1).__plus((2))).__star((3)),(9));
 self._assert_equals_((1).__plus((2).__star((3))),(7));
 return self}, function($ctx1) {$ctx1.fill(self,"testArithmetic",{},smalltalk.NumberTest)})},
 args: [],
-source: "testArithmetic\x0a\x09\x0a\x09\x22We rely on JS here, so we won't test complex behavior, just check if\x0a\x09message sends are corrects\x22\x0a\x0a\x09self assert: 1.5 + 1 equals: 2.5.\x0a\x09self assert: 2 - 1 equals: 1.\x0a\x09self assert: -2 - 1 equals: -3.\x0a\x09self assert: 12 / 2 equals: 6.\x0a\x09self assert: 3 * 4 equals: 12.\x0a\x0a\x09\x22Simple parenthesis and execution order\x22\x0a\x09self assert: 1 + 2 * 3 equals: 9.\x0a\x09self assert: 1 + (2 * 3) equals: 7",
-messageSends: ["assert:equals:", "+", "-", "/", "*"],
+source: "testArithmetic\x0a\x09\x0a\x09\x22We rely on JS here, so we won't test complex behavior, just check if\x0a\x09message sends are corrects\x22\x0a\x0a\x09self assert: 1.5 + 1 equals: 2.5.\x0a\x09self assert: 2 - 1 equals: 1.\x0a\x09self assert: -2 - 1 equals: -3.\x0a\x09self assert: 12 / 2 equals: 6.\x0a\x09self assert: 3 * 4 equals: 12.\x0a\x09self assert: 7 // 2 equals: 3.\x0a\x09self assert: 7 \x5c\x5c 2 equals: 1.\x0a\x0a\x09\x22Simple parenthesis and execution order\x22\x0a\x09self assert: 1 + 2 * 3 equals: 9.\x0a\x09self assert: 1 + (2 * 3) equals: 7",
+messageSends: ["assert:equals:", "+", "-", "/", "*", "//", "\x5c\x5c"],
 referencedClasses: []
 }),
 smalltalk.NumberTest);
@@ -3809,6 +3811,25 @@ referencedClasses: ["MessageNotUnderstood"]
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testLog",
+category: 'tests',
+fn: function (){
+var self=this;
+function $Number(){return smalltalk.Number||(typeof Number=="undefined"?nil:Number)}
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((10000)._log(),(4));
+self._assert_equals_((512)._log_((2)),(9));
+self._assert_equals_(_st(_st($Number())._e())._ln(),(1));
+return self}, function($ctx1) {$ctx1.fill(self,"testLog",{},smalltalk.NumberTest)})},
+args: [],
+source: "testLog\x0a\x09self assert: 10000 log equals: 4.\x0a\x09self assert: (512 log: 2) equals: 9.\x0a\x09self assert: Number e ln equals: 1.",
+messageSends: ["assert:equals:", "log", "log:", "ln", "e"],
+referencedClasses: ["Number"]
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testMinMax",
@@ -3871,6 +3892,26 @@ referencedClasses: []
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testRaisedTo",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((2)._raisedTo_((4)),(16));
+self._assert_equals_((2)._raisedTo_((0)),(1));
+self._assert_equals_((2)._raisedTo_((-3)),(0.125));
+self._assert_equals_((4)._raisedTo_((0.5)),(2));
+self._assert_equals_((2).__star_star((4)),(16));
+return self}, function($ctx1) {$ctx1.fill(self,"testRaisedTo",{},smalltalk.NumberTest)})},
+args: [],
+source: "testRaisedTo\x0a\x09self assert: (2 raisedTo: 4) equals: 16.\x0a\x09self assert: (2 raisedTo: 0) equals: 1.\x0a\x09self assert: (2 raisedTo: -3) equals: 0.125.\x0a\x09self assert: (4 raisedTo: 0.5) equals: 2.\x0a\x09\x0a\x09self assert: 2 ** 4 equals: 16.",
+messageSends: ["assert:equals:", "raisedTo:", "**"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testRounded",
@@ -3889,6 +3930,24 @@ referencedClasses: []
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testSign",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((5)._sign(),(1));
+self._assert_equals_((0)._sign(),(0));
+self._assert_equals_((-1.4)._sign(),(-1));
+return self}, function($ctx1) {$ctx1.fill(self,"testSign",{},smalltalk.NumberTest)})},
+args: [],
+source: "testSign\x0a\x09self assert: 5 sign equals: 1.\x0a\x09self assert: 0 sign equals: 0.\x0a\x09self assert: -1.4 sign equals: -1.",
+messageSends: ["assert:equals:", "sign"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testSqrt",
@@ -3988,6 +4047,27 @@ referencedClasses: ["Error"]
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testTrigonometry",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((0)._cos(),(1));
+self._assert_equals_((0)._sin(),(0));
+self._assert_equals_((0)._tan(),(0));
+self._assert_equals_((1)._arcCos(),(0));
+self._assert_equals_((0)._arcSin(),(0));
+self._assert_equals_((0)._arcTan(),(0));
+return self}, function($ctx1) {$ctx1.fill(self,"testTrigonometry",{},smalltalk.NumberTest)})},
+args: [],
+source: "testTrigonometry\x0a\x09self assert: 0 cos equals: 1.\x0a\x09self assert: 0 sin equals: 0.\x0a\x09self assert: 0 tan equals: 0.\x0a\x09self assert: 1 arcCos equals: 0.\x0a\x09self assert: 0 arcSin equals: 0.\x0a\x09self assert: 0 arcTan equals: 0.",
+messageSends: ["assert:equals:", "cos", "sin", "tan", "arcCos", "arcSin", "arcTan"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testTruncated",

+ 68 - 6
st/Kernel-Objects.st

@@ -775,12 +775,8 @@ negated
 	^0 - self
 !
 
-sqrt
-	<return Math.sqrt(self)>
-!
-
-squared
-	^self * self
+// aNumber
+	^(self / aNumber) floor
 ! !
 
 !Number methodsFor: 'comparing'!
@@ -948,6 +944,68 @@ to: stop do: aBlock
 			nextValue := nextValue + 1]
 ! !
 
+!Number methodsFor: 'mathematical functions'!
+
+sqrt
+	<return Math.sqrt(self)>
+!
+
+squared
+	^self * self
+!
+
+cos
+	<return Math.cos(self);>
+!
+
+sin
+	<return Math.sin(self);>
+!
+
+tan
+	<return Math.tan(self);>
+!
+
+arcCos
+	<return Math.acos(self);>
+!
+
+arcSin
+	<return Math.asin(self);>
+!
+
+arcTan
+	<return Math.atan(self);>
+!
+
+log
+	<return Math.log(self) / Math.LN10;>
+!
+
+log: aNumber
+	<return Math.log(self) / Math.log(aNumber);>
+!
+
+raisedTo: exponent
+	<return Math.pow(self, exponent);>
+!
+
+sign
+	self isZero 
+		ifTrue: [ ^ 0 ].
+	self positive
+		ifTrue: [ ^ 1 ]
+		ifFalse: [ ^ -1 ].
+!
+
+** exponent
+	^self raisedTo: exponent
+!
+
+ln
+	<return Math.log(self);>
+! !
+
 !Number methodsFor: 'printing'!
 
 printOn: aStream
@@ -1002,6 +1060,10 @@ heliosClass
 
 pi
 	<return Math.PI>
+!
+
+e
+	<return Math.E;>
 ! !
 
 Object subclass: #Point

+ 32 - 0
st/Kernel-Tests.st

@@ -1301,6 +1301,8 @@ testArithmetic
 	self assert: -2 - 1 equals: -3.
 	self assert: 12 / 2 equals: 6.
 	self assert: 3 * 4 equals: 12.
+	self assert: 7 // 2 equals: 3.
+	self assert: 7 \\ 2 equals: 1.
 
 	"Simple parenthesis and execution order"
 	self assert: 1 + 2 * 3 equals: 9.
@@ -1496,6 +1498,36 @@ testTruncated
 	self assert: 3 truncated equals: 3.
 	self assert: 3.212 truncated equals: 3.
 	self assert: 3.51 truncated equals: 3
+!
+
+testTrigonometry
+	self assert: 0 cos equals: 1.
+	self assert: 0 sin equals: 0.
+	self assert: 0 tan equals: 0.
+	self assert: 1 arcCos equals: 0.
+	self assert: 0 arcSin equals: 0.
+	self assert: 0 arcTan equals: 0.
+!
+
+testLog
+	self assert: 10000 log equals: 4.
+	self assert: (512 log: 2) equals: 9.
+	self assert: Number e ln equals: 1.
+!
+
+testRaisedTo
+	self assert: (2 raisedTo: 4) equals: 16.
+	self assert: (2 raisedTo: 0) equals: 1.
+	self assert: (2 raisedTo: -3) equals: 0.125.
+	self assert: (4 raisedTo: 0.5) equals: 2.
+	
+	self assert: 2 ** 4 equals: 16.
+!
+
+testSign
+	self assert: 5 sign equals: 1.
+	self assert: 0 sign equals: 0.
+	self assert: -1.4 sign equals: -1.
 ! !
 
 Object subclass: #ObjectMock