PageRenderTime 55ms CodeModel.GetById 8ms app.highlight 42ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2dist110511/src/edu/vub/at/objects/natives/NATNumber.java

http://ambienttalk.googlecode.com/
Java | 654 lines | 470 code | 48 blank | 136 comment | 29 complexity | fe5ba223f978af2fc2d38f167cda9523 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * NATNumber.java created on 26-jul-2006 at 16:32:54
  4 * (c) Programming Technology Lab, 2006 - 2007
  5 * Authors: Tom Van Cutsem & Stijn Mostinckx
  6 * 
  7 * Permission is hereby granted, free of charge, to any person
  8 * obtaining a copy of this software and associated documentation
  9 * files (the "Software"), to deal in the Software without
 10 * restriction, including without limitation the rights to use,
 11 * copy, modify, merge, publish, distribute, sublicense, and/or
 12 * sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following
 14 * conditions:
 15 *
 16 * The above copyright notice and this permission notice shall be
 17 * included in all copies or substantial portions of the Software.
 18 *
 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 26 * OTHER DEALINGS IN THE SOFTWARE.
 27 */
 28package edu.vub.at.objects.natives;
 29
 30import edu.vub.at.eval.Evaluator;
 31import edu.vub.at.exceptions.InterpreterException;
 32import edu.vub.at.exceptions.XIllegalArgument;
 33import edu.vub.at.exceptions.XSelectorNotFound;
 34import edu.vub.at.exceptions.XTypeMismatch;
 35import edu.vub.at.objects.ATBoolean;
 36import edu.vub.at.objects.ATClosure;
 37import edu.vub.at.objects.ATContext;
 38import edu.vub.at.objects.ATFraction;
 39import edu.vub.at.objects.ATMethod;
 40import edu.vub.at.objects.ATNil;
 41import edu.vub.at.objects.ATNumber;
 42import edu.vub.at.objects.ATNumeric;
 43import edu.vub.at.objects.ATObject;
 44import edu.vub.at.objects.ATTable;
 45import edu.vub.at.objects.ATText;
 46import edu.vub.at.objects.coercion.NativeTypeTags;
 47import edu.vub.at.objects.grammar.ATSymbol;
 48import edu.vub.at.objects.mirrors.DirectNativeMethod;
 49import edu.vub.at.objects.mirrors.Reflection;
 50import edu.vub.util.TempFieldGenerator;
 51
 52import java.util.HashMap;
 53
 54/**
 55 * The native implementation of an AmbientTalk number.
 56 * A number is implemented by a Java int.
 57 * 
 58 * @author smostinc
 59 */
 60public final class NATNumber extends NATNumeric implements ATNumber {
 61	
 62	public static final NATNumber ZERO = new NATNumber(0);
 63	public static final NATNumber ONE = new NATNumber(1);
 64	public static final NATNumber MONE = new NATNumber(-1);
 65	
 66	public final int javaValue;
 67	
 68	/**
 69	 * This method currently serves as a hook for number creation.
 70	 * Currently number objects are not reused, but this might change in the future.
 71	 */
 72	public static final NATNumber atValue(int javaNumber) {
 73		return new NATNumber(javaNumber);
 74	}
 75	
 76	private NATNumber(int javaNumber) {
 77		javaValue = javaNumber;
 78	}
 79
 80    public ATBoolean base__opeql__opeql_(ATObject comparand) throws XTypeMismatch {
 81    	if (comparand.isNativeNumber()) {
 82    		return NATBoolean.atValue(javaValue == comparand.asNativeNumber().javaValue);
 83    	} else {
 84    		return NATBoolean._FALSE_;
 85    	}
 86    }
 87	
 88	public ATNumber asNumber() throws XTypeMismatch { return this; }
 89	
 90	public boolean isNativeNumber() { return true; }
 91	
 92	public NATNumber asNativeNumber() { return this; }
 93	
 94	public NATText meta_print() throws InterpreterException {
 95        return NATText.atValue(String.valueOf(javaValue));
 96	}
 97	
 98	public NATText impl_asCode(TempFieldGenerator objectMap) throws InterpreterException {
 99		return NATText.atValue(String.valueOf(javaValue));
100	}
101	
102    public ATTable meta_typeTags() throws InterpreterException {
103    	return NATTable.of(NativeTypeTags._NUMBER_, NativeTypeTags._ISOLATE_);
104    }
105	
106	// contract with NATNumeric
107	protected double getJavaValue() { return javaValue; }
108	
109	public int hashCode() { return javaValue; }
110	
111	/* -----------------------------------
112	 * - base-level interface to numbers -
113	 * ----------------------------------- */
114	
115	// iteration constructs
116	
117	/**
118	 * NBR(n).doTimes: { |i| code } => for i = 1 to n do code.eval(i) ; nil
119	 */
120	public ATNil base_doTimes_(ATClosure code) throws InterpreterException {
121		for (int i = 1; i <= javaValue; i++) {
122			code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
123		}
124		return Evaluator.getNil();
125	}
126	
127	/**
128	 * NBR(start).to: NBR(stop) do: { |i| code } => for i = start to stop do code.eval(i) ; nil
129	 * Also works if stop > start, in which case it becomes a downTo.
130	 * 
131	 * If start = stop, the code is not executed.
132	 */
133	public ATNil base_to_do_(ATNumber end, ATClosure code) throws InterpreterException {
134		return this.base_to_step_do_(end, NATNumber.ONE, code);
135	}
136	
137	/**
138	 * NBR(start).to: NBR(stop) step: NBR(inc) do: { |i| code } =>
139	 *   for i = start; i < stop; i++ do code.eval(i) ; nil
140	 * Also works if stop > start, in which case it becomes a downTo.
141	 */
142	public ATNil base_to_step_do_(ATNumber end, ATNumber inc, ATClosure code) throws InterpreterException {
143		int stop = end.asNativeNumber().javaValue;
144		int step = inc.asNativeNumber().javaValue;
145		int start = javaValue;
146		if (start > stop) {
147			for (int i = start; i > stop; i -= step) {
148				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
149			}
150		} else {
151			for (int i = start; i < stop; i+= step) {
152				code.base_apply(NATTable.atValue(new ATObject[] { NATNumber.atValue(i) }));
153			}
154		}
155		return Evaluator.getNil();
156	}
157	
158	/**
159	 * NBR(start) ** NBR(stop) => [ start, ..., stop [
160	 * 
161	 * Example:
162	 *  2 ** 5 => [ 2, 3, 4 ]
163	 *  5 ** 2 => [ 5, 4, 3 ]
164	 */
165	public ATTable base__optms__optms_(ATNumber end) throws InterpreterException {
166		int stop = end.asNativeNumber().javaValue;
167		int start = javaValue;
168		if (start < stop) {
169			ATObject[] tbl = new ATObject[stop - start];
170			for (int i = 0; i < tbl.length; i++) {
171				tbl[i] = NATNumber.atValue(start + i);
172			}
173			return NATTable.atValue(tbl);
174		} else {
175			ATObject[] tbl = new ATObject[start - stop];
176			for (int i = 0; i < tbl.length; i++) {
177				tbl[i] = NATNumber.atValue(start - i);
178			}
179			return NATTable.atValue(tbl);
180		}
181	}
182	
183	/**
184	 * NBR(start) *** NBR(stop) => [ start, ..., stop ]
185	 * 
186	 * Example:
187	 *  2 *** 5 => [ 2, 3, 4, 5 ]
188	 *  5 *** 2 => [ 5, 4, 3, 2 ]
189	 */
190	public ATTable base__optms__optms__optms_(ATNumber end) throws InterpreterException {
191		// x *** y == x ** y+1 iff x < y
192		// x *** y == x ** y-1 iff y > x
193		int stop = end.asNativeNumber().javaValue;
194		if (javaValue <= stop)
195		    return this.base__optms__optms_(end.base_inc().asNumber());
196		else
197			return this.base__optms__optms_(end.base_dec().asNumber());
198	}
199
200	// Number arithmetic operations
201	
202	/**
203	 * NBR(n).inc() => NBR(n+1)
204	 */
205	public ATNumber base_inc() {
206		return NATNumber.atValue(javaValue+1);
207	}
208	
209	/**
210	 * NBR(n).dec() => NBR(n-1)
211	 */
212	public ATNumber base_dec() {
213		return NATNumber.atValue(javaValue-1);
214	}
215	
216	/**
217	 * NBR(n).abs() => NBR(abs(n))
218	 */
219	public ATNumber base_abs() {
220		return NATNumber.atValue(Math.abs(javaValue));
221	}
222	
223	public ATNumber base_ceiling() throws InterpreterException {
224		return this;
225	}
226
227	public ATNumber base_floor() throws InterpreterException {
228		return this;
229	}
230
231	public ATNumber base_round() throws InterpreterException {
232		return this;
233	}
234
235	/**
236	 * NBR(start) ?? NBR(stop) => FRC(n) where n chosen randomly in [ start, stop [
237	 */
238	public ATFraction base__opque__opque_(ATNumber nbr) throws InterpreterException {
239		int stop = nbr.asNativeNumber().javaValue;
240		double rnd = Math.random(); // 0 <= rnd < 1.0
241		double frc = (rnd * (stop - javaValue)) + javaValue;
242		return NATFraction.atValue(frc);
243	}
244	
245	/**
246	 * NBR(n) % NBR(r) => NBR(n % r)
247	 */
248	public ATNumber base__oprem_(ATNumber n) throws InterpreterException {
249		return NATNumber.atValue(javaValue % n.asNativeNumber().javaValue);
250	}
251	
252	/**
253	 * NBR(n) /- NBR(d) => NBR(n / d)
254	 */
255	public ATNumber base__opdiv__opmns_(ATNumber n) throws InterpreterException {
256		return NATNumber.atValue(javaValue / n.asNativeNumber().javaValue);
257	}
258	
259	// Numeric arithmetic operations
260	
261	// addition +
262	public ATNumeric base__oppls_(ATNumeric other) throws InterpreterException {
263		return other.base_addNumber(this);
264	}
265	public ATNumeric base_addNumber(ATNumber other) throws InterpreterException {
266		return NATNumber.atValue(other.asNativeNumber().javaValue + javaValue);
267	}
268	public ATNumeric base_addFraction(ATFraction other) throws InterpreterException {
269		return NATFraction.atValue(other.asNativeFraction().javaValue + javaValue);
270	}
271	
272	// subtraction -
273	public ATNumeric base__opmns_(ATNumeric other) throws InterpreterException {
274		return other.base_subtractNumber(this);
275	}
276	public ATNumeric base_subtractNumber(ATNumber other) throws InterpreterException {
277		return NATNumber.atValue(other.asNativeNumber().javaValue - javaValue);
278	}
279	public ATNumeric base_subtractFraction(ATFraction other) throws InterpreterException {
280		return NATFraction.atValue(other.asNativeFraction().javaValue - javaValue);
281	}
282	
283	// multiplication *
284	public ATNumeric base__optms_(ATNumeric other) throws InterpreterException {
285		return other.base_timesNumber(this);
286	}
287	public ATNumeric base_timesNumber(ATNumber other) throws InterpreterException {
288		return NATNumber.atValue(other.asNativeNumber().javaValue * javaValue);
289	}
290	public ATNumeric base_timesFraction(ATFraction other) throws InterpreterException {
291		return NATFraction.atValue(other.asNativeFraction().javaValue * javaValue);
292	}
293	
294	// division /
295	public ATNumeric base__opdiv_(ATNumeric other) throws InterpreterException {
296		return other.base_divideNumber(this);
297	}
298	public ATNumeric base_divideNumber(ATNumber other) throws InterpreterException {
299		if (javaValue == 0)
300			throw new XIllegalArgument("Division by zero: " + other);
301		return NATFraction.atValue((other.asNativeNumber().javaValue * 1.0) / javaValue);
302	}
303	public ATNumeric base_divideFraction(ATFraction other) throws InterpreterException {
304		if (javaValue == 0)
305			throw new XIllegalArgument("Division by zero: " + other);
306		return NATFraction.atValue(other.asNativeFraction().javaValue / javaValue);
307	}
308	
309	// comparison: generalized equality <=>
310	public ATNumeric base__opltx__opeql__opgtx_(ATNumeric other) throws InterpreterException {
311		return other.base_gequalsNumber(this);
312	}
313	public ATNumeric base_gequalsNumber(ATNumber other) throws InterpreterException {
314		int n = other.asNativeNumber().javaValue;
315		if (n < javaValue) {
316			return NATNumber.MONE; // -1
317		} else if (n > javaValue) {
318			return NATNumber.ONE;  // +1
319		} else {
320			return NATNumber.ZERO; // 0
321		}
322	}
323	public ATNumeric base_gequalsFraction(ATFraction other) throws InterpreterException {
324		double n = other.asNativeFraction().javaValue;
325		if (n < javaValue) {
326			return NATNumber.MONE; // -1
327		} else if (n > javaValue) {
328			return NATNumber.ONE;  // +1
329		} else {
330			return NATNumber.ZERO; // 0
331		}
332	}
333	
334	/**
335	 * Converts an AmbientTalk number representing a time period in milliseconds
336	 * into a Java long representing the same time period in milliseconds.
337	 * 
338	 * @return a Java long representation of self.
339	 */
340	public long base_millisec() throws InterpreterException {
341		return javaValue;
342	}
343	
344	/**
345	 * Converts an AmbientTalk number representing a time period in seconds
346	 * into a Java long * 1000 representing a time period in milliseconds.
347	 * 
348	 * @return a Java long representation of self * 1000.
349	 */
350	public long base_seconds() throws InterpreterException {
351		return javaValue * 1000;
352	}
353	
354	/**
355	 * Converts an AmbientTalk number representing a minute time period
356	 * into a Java long * 1000 * 60 representing a
357	 * millisecond time period.
358	 * 
359	 * @return a Java long representation of self * 1000 * 60.
360	 */
361	public long base_minutes() throws InterpreterException {
362		return javaValue * 60 * 1000;
363	}
364	
365	/**
366	 * NUM(n).toText() = TXT(String.valueOf(n))
367	 */
368	public ATText base_toText() throws InterpreterException {
369		return NATText.atValue(String.valueOf(javaValue));
370	}
371	
372	/**
373	 * This hashmap stores all native methods of native AmbientTalk numbers.
374	 * It is populated when this class is loaded, and shared between all
375	 * AmbientTalk actors on this VM. This is safe, since {@link DirectNativeMethod}
376	 * instances are all immutable.
377	 */
378	private static final HashMap<String, ATMethod> _meths = new HashMap<String, ATMethod>();
379	
380	// initialize NATNumber methods
381	static {
382		_meths.put("doTimes:", new DirectNativeMethod("doTimes:") {
383			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
384				NATNumber self = ctx.base_receiver().asNativeNumber();
385				checkArity(args, 1);
386				ATClosure code = get(args, 1).asClosure();
387				return self.base_doTimes_(code);
388			}
389		});
390		_meths.put("to:do:", new DirectNativeMethod("to:do:") {
391			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
392				NATNumber self = ctx.base_receiver().asNativeNumber();
393				checkArity(args, 2);
394				ATNumber nbr = get(args, 1).asNumber();
395				ATClosure code = get(args, 2).asClosure();
396				return self.base_to_do_(nbr, code);
397			}
398		});
399		_meths.put("to:step:do:", new DirectNativeMethod("to:step:do:") {
400			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
401				NATNumber self = ctx.base_receiver().asNativeNumber();
402				checkArity(args, 3);
403				ATNumber nbr = get(args, 1).asNumber();
404				ATNumber step = get(args, 2).asNumber();
405				ATClosure code = get(args, 3).asClosure();
406				return self.base_to_step_do_(nbr, step, code);
407			}
408		});
409		_meths.put("**", new DirectNativeMethod("**") {
410			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
411				NATNumber self = ctx.base_receiver().asNativeNumber();
412				checkArity(args, 1);
413				ATNumber end = get(args, 1).asNumber();
414				return self.base__optms__optms_(end);
415			}
416		});
417		_meths.put("***", new DirectNativeMethod("***") {
418			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
419				NATNumber self = ctx.base_receiver().asNativeNumber();
420				checkArity(args, 1);
421				ATNumber end = get(args, 1).asNumber();
422				return self.base__optms__optms__optms_(end);
423			}
424		});
425		_meths.put("inc", new DirectNativeMethod("inc") {
426			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
427				NATNumber self = ctx.base_receiver().asNativeNumber();
428				checkArity(args, 0);
429				return self.base_inc();
430			}
431		});
432		_meths.put("dec", new DirectNativeMethod("dec") {
433			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
434				NATNumber self = ctx.base_receiver().asNativeNumber();
435				checkArity(args, 0);
436				return self.base_dec();
437			}
438		});
439		_meths.put("abs", new DirectNativeMethod("abs") {
440			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
441				NATNumber self = ctx.base_receiver().asNativeNumber();
442				checkArity(args, 0);
443				return self.base_abs();
444			}
445		});
446		_meths.put("ceiling", new DirectNativeMethod("ceiling") {
447			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
448				NATNumber self = ctx.base_receiver().asNativeNumber();
449				checkArity(args, 0);
450				return self.base_ceiling();
451			}
452		});
453		_meths.put("floor", new DirectNativeMethod("floor") {
454			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
455				NATNumber self = ctx.base_receiver().asNativeNumber();
456				checkArity(args, 0);
457				return self.base_floor();
458			}
459		});
460		_meths.put("round", new DirectNativeMethod("round") {
461			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
462				NATNumber self = ctx.base_receiver().asNativeNumber();
463				checkArity(args, 0);
464				return self.base_round();
465			}
466		});
467		_meths.put("??", new DirectNativeMethod("??") {
468			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
469				NATNumber self = ctx.base_receiver().asNativeNumber();
470				checkArity(args, 1);
471				ATNumber nbr = get(args,1).asNumber();
472				return self.base__opque__opque_(nbr);
473			}
474		});
475		_meths.put("%", new DirectNativeMethod("%") {
476			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
477				NATNumber self = ctx.base_receiver().asNativeNumber();
478				checkArity(args, 1);
479				ATNumber nbr = get(args,1).asNumber();
480				return self.base__oprem_(nbr);
481			}
482		});
483		_meths.put("/-", new DirectNativeMethod("/-") {
484			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
485				NATNumber self = ctx.base_receiver().asNativeNumber();
486				checkArity(args, 1);
487				ATNumber nbr = get(args,1).asNumber();
488				return self.base__opdiv__opmns_(nbr);
489			}
490		});
491		_meths.put("+", new DirectNativeMethod("+") {
492			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
493				NATNumber self = ctx.base_receiver().asNativeNumber();
494				checkArity(args, 1);
495				ATNumeric nbr = get(args,1).asNativeNumeric();
496				return self.base__oppls_(nbr);
497			}
498		});
499		_meths.put("addNumber", new DirectNativeMethod("addNumber") {
500			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
501				NATNumber self = ctx.base_receiver().asNativeNumber();
502				checkArity(args, 1);
503				ATNumber nbr = get(args,1).asNumber();
504				return self.base_addNumber(nbr);
505			}
506		});
507		_meths.put("addFraction", new DirectNativeMethod("addFraction") {
508			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
509				NATNumber self = ctx.base_receiver().asNativeNumber();
510				checkArity(args, 1);
511				ATFraction frc = get(args,1).asNativeFraction();
512				return self.base_addFraction(frc);
513			}
514		});
515		_meths.put("-", new DirectNativeMethod("-") {
516			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
517				NATNumber self = ctx.base_receiver().asNativeNumber();
518				checkArity(args, 1);
519				ATNumeric nbr = get(args,1).asNativeNumeric();
520				return self.base__opmns_(nbr);
521			}
522		});
523		_meths.put("subtractNumber", new DirectNativeMethod("subtractNumber") {
524			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
525				NATNumber self = ctx.base_receiver().asNativeNumber();
526				checkArity(args, 1);
527				ATNumber nbr = get(args,1).asNumber();
528				return self.base_subtractNumber(nbr);
529			}
530		});
531		_meths.put("subtractFraction", new DirectNativeMethod("subtractFraction") {
532			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
533				NATNumber self = ctx.base_receiver().asNativeNumber();
534				checkArity(args, 1);
535				ATFraction frc = get(args,1).asNativeFraction();
536				return self.base_subtractFraction(frc);
537			}
538		});
539		_meths.put("*", new DirectNativeMethod("*") {
540			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
541				NATNumber self = ctx.base_receiver().asNativeNumber();
542				checkArity(args, 1);
543				ATNumeric nbr = get(args,1).asNativeNumeric();
544				return self.base__optms_(nbr);
545			}
546		});
547		_meths.put("timesNumber", new DirectNativeMethod("timesNumber") {
548			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
549				NATNumber self = ctx.base_receiver().asNativeNumber();
550				checkArity(args, 1);
551				ATNumber nbr = get(args,1).asNumber();
552				return self.base_timesNumber(nbr);
553			}
554		});
555		_meths.put("timesFraction", new DirectNativeMethod("timesFraction") {
556			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
557				NATNumber self = ctx.base_receiver().asNativeNumber();
558				checkArity(args, 1);
559				ATFraction frc = get(args,1).asNativeFraction();
560				return self.base_timesFraction(frc);
561			}
562		});
563		_meths.put("/", new DirectNativeMethod("/") {
564			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
565				NATNumber self = ctx.base_receiver().asNativeNumber();
566				checkArity(args, 1);
567				ATNumeric nbr = get(args,1).asNativeNumeric();
568				return self.base__opdiv_(nbr);
569			}
570		});
571		_meths.put("divideNumber", new DirectNativeMethod("divideNumber") {
572			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
573				NATNumber self = ctx.base_receiver().asNativeNumber();
574				checkArity(args, 1);
575				ATNumber nbr = get(args,1).asNumber();
576				return self.base_divideNumber(nbr);
577			}
578		});
579		_meths.put("divideFraction", new DirectNativeMethod("divideFraction") {
580			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
581				NATNumber self = ctx.base_receiver().asNativeNumber();
582				checkArity(args, 1);
583				ATFraction frc = get(args,1).asNativeFraction();
584				return self.base_divideFraction(frc);
585			}
586		});
587		_meths.put("<=>", new DirectNativeMethod("<=>") {
588			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
589				NATNumber self = ctx.base_receiver().asNativeNumber();
590				checkArity(args, 1);
591				ATNumeric nbr = get(args,1).asNativeNumeric();
592				return self.base__opltx__opeql__opgtx_(nbr);
593			}
594		});
595		_meths.put("gequalsNumber", new DirectNativeMethod("gequalsNumber") {
596			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
597				NATNumber self = ctx.base_receiver().asNativeNumber();
598				checkArity(args, 1);
599				ATNumber nbr = get(args,1).asNumber();
600				return self.base_gequalsNumber(nbr);
601			}
602		});
603		_meths.put("gequalsFraction", new DirectNativeMethod("gequalsFraction") {
604			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
605				NATNumber self = ctx.base_receiver().asNativeNumber();
606				checkArity(args, 1);
607				ATFraction frc = get(args,1).asNativeFraction();
608				return self.base_gequalsFraction(frc);
609			}
610		});
611		_meths.put("==", new DirectNativeMethod("==") {
612			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
613				NATNumber self = ctx.base_receiver().asNativeNumber();
614				checkArity(args, 1);
615				ATObject comparand = get(args, 1);
616				return self.base__opeql__opeql_(comparand);
617			}
618		});
619		_meths.put("toText", new DirectNativeMethod("toText") {
620			public ATObject base_apply(ATTable args, ATContext ctx) throws InterpreterException {
621				NATNumber self = ctx.base_receiver().asNativeNumber();
622				checkArity(args, 0);
623				return self.base_toText();
624			}
625		});
626	}
627	
628	/**
629	 * Overrides the default AmbientTalk native object behavior of extracting native
630	 * methods based on the 'base_' naming convention. Instead, native AT numbers use
631	 * an explicit hashmap of native methods. This is much faster than the default
632	 * behavior, which requires reflection.
633	 */
634	protected boolean hasLocalMethod(ATSymbol atSelector) throws InterpreterException {
635		if  (_meths.containsKey(atSelector.base_text().asNativeText().javaValue)) {
636			return true;
637		} else {
638			return super.hasLocalMethod(atSelector);
639		}
640	}
641	
642	/**
643	 * @see NATNumber#hasLocalMethod(ATSymbol)
644	 */
645	protected ATMethod getLocalMethod(ATSymbol selector) throws InterpreterException {
646		ATMethod val = _meths.get(selector.base_text().asNativeText().javaValue);
647		if (val == null) {
648			return super.getLocalMethod(selector);
649			//throw new XSelectorNotFound(selector, this);			
650		}
651		return val;
652	}
653	
654}