double_prims.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.27 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_double_prims.cpp.incl"
00026 # include <math.h>
00027 # include <float.h>
00028 
00029 TRACE_FUNC(TraceDoublePrims, "double")
00030 
00031 int doubleOopPrimitives::number_of_calls;
00032 
00033 inline static oop new_double(double value) {
00034   doubleOop d = as_doubleOop(Universe::allocate(sizeof(doubleOopDesc)/oopSize));
00035   d->init_untagged_contents_mark();
00036   d->set_klass_field(doubleKlassObj);
00037   d->set_value(value);
00038   return d;
00039 }
00040 
00041 # define ASSERT_RECEIVER assert(receiver->is_double(), "receiver must be double")
00042 
00043 # define DOUBLE_RELATIONAL_OP(op)                                     \
00044   ASSERT_RECEIVER;                                                    \
00045   if (!argument->is_double())                                         \
00046     return markSymbol(vmSymbols::first_argument_has_wrong_type());    \
00047   return doubleOop(receiver)->value() op doubleOop(argument)->value() \
00048          ? trueObj : falseObj
00049 
00050 # define DOUBLE_ARITH_OP(op)                                          \
00051   ASSERT_RECEIVER;                                                    \
00052   if (!argument->is_double())                                         \
00053     return markSymbol(vmSymbols::first_argument_has_wrong_type());    \
00054   return new_double(doubleOop(receiver)->value() op doubleOop(argument)->value())
00055 
00056 
00057 PRIM_DECL_2(doubleOopPrimitives::lessThan, oop receiver, oop argument) {
00058   PROLOGUE_2("lessThan", receiver, argument); 
00059   DOUBLE_RELATIONAL_OP(<);
00060 }
00061 
00062 PRIM_DECL_2(doubleOopPrimitives::greaterThan, oop receiver, oop argument) {
00063   PROLOGUE_2("greaterThan", receiver, argument);
00064   DOUBLE_RELATIONAL_OP(>);
00065 }
00066 
00067 PRIM_DECL_2(doubleOopPrimitives::lessThanOrEqual, oop receiver, oop argument) {
00068   PROLOGUE_2("lessThanOrEqual", receiver, argument);
00069   DOUBLE_RELATIONAL_OP(<=);
00070 }
00071 
00072 PRIM_DECL_2(doubleOopPrimitives::greaterThanOrEqual, oop receiver, oop argument) {
00073   PROLOGUE_2("greaterThanOrEqual", receiver, argument);
00074   DOUBLE_RELATIONAL_OP(>=);
00075 }
00076 
00077 PRIM_DECL_2(doubleOopPrimitives::equal, oop receiver, oop argument) {
00078   PROLOGUE_2("equal", receiver, argument);
00079   DOUBLE_RELATIONAL_OP(==);
00080 }
00081 
00082 PRIM_DECL_2(doubleOopPrimitives::notEqual, oop receiver, oop argument) {
00083   PROLOGUE_2("notEqual", receiver, argument);
00084   DOUBLE_RELATIONAL_OP(!=);
00085 }
00086 
00087 /*
00088 PRIM_DECL_2(doubleOopPrimitives::add, oop receiver, oop argument) {
00089   PROLOGUE_2("add", receiver, argument);
00090   DOUBLE_ARITH_OP(+);
00091 }
00092 
00093 PRIM_DECL_2(doubleOopPrimitives::subtract, oop receiver, oop argument) {
00094   PROLOGUE_2("subtract", receiver, argument);
00095   DOUBLE_ARITH_OP(-);
00096 }
00097 
00098 
00099 PRIM_DECL_2(doubleOopPrimitives::multiply, oop receiver, oop argument) {
00100   PROLOGUE_2("multiply", receiver, argument);
00101   DOUBLE_ARITH_OP(*);
00102 }
00103 
00104 PRIM_DECL_2(doubleOopPrimitives::divide, oop receiver, oop argument) {
00105   PROLOGUE_2("divide", receiver, argument);
00106   DOUBLE_ARITH_OP(/);
00107 }
00108 */
00109 
00110 PRIM_DECL_2(doubleOopPrimitives::mod, oop receiver, oop argument) {
00111   PROLOGUE_2("mod", receiver, argument);
00112   ASSERT_RECEIVER;
00113   if (!argument->is_double())
00114     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00115 
00116   double result = fmod(doubleOop(receiver)->value(), doubleOop(argument)->value());
00117   return new_double(result);
00118 }
00119 
00120 PRIM_DECL_1(doubleOopPrimitives::cosine, oop receiver) {
00121   PROLOGUE_1("cosine", receiver);
00122   ASSERT_RECEIVER;
00123   return new_double(cos(doubleOop(receiver)->value()));
00124 }
00125 
00126 PRIM_DECL_1(doubleOopPrimitives::sine, oop receiver) {
00127   PROLOGUE_1("sine", receiver);
00128   ASSERT_RECEIVER;
00129   return new_double(sin(doubleOop(receiver)->value()));
00130 }
00131 
00132 PRIM_DECL_1(doubleOopPrimitives::tangent, oop receiver) {
00133   PROLOGUE_1("tangent", receiver);
00134   ASSERT_RECEIVER;
00135   return new_double(tan(doubleOop(receiver)->value()));
00136 }
00137 
00138 
00139 PRIM_DECL_1(doubleOopPrimitives::arcCosine, oop receiver) {
00140   PROLOGUE_1("arcCosine", receiver);
00141   ASSERT_RECEIVER;
00142   return new_double(acos(doubleOop(receiver)->value()));
00143 }
00144 
00145 PRIM_DECL_1(doubleOopPrimitives::arcSine, oop receiver) {
00146   PROLOGUE_1("arcSine", receiver);
00147   ASSERT_RECEIVER;
00148   return new_double(asin(doubleOop(receiver)->value()));
00149 }
00150 
00151 PRIM_DECL_1(doubleOopPrimitives::arcTangent, oop receiver) {
00152   PROLOGUE_1("arcTangent", receiver);
00153   ASSERT_RECEIVER;
00154   return new_double(atan(doubleOop(receiver)->value()));
00155 }
00156 
00157 PRIM_DECL_1(doubleOopPrimitives::hyperbolicCosine, oop receiver) {
00158   PROLOGUE_1("hyperbolicCosine", receiver);
00159   ASSERT_RECEIVER;
00160   return new_double(cosh(doubleOop(receiver)->value()));
00161 }
00162 
00163 PRIM_DECL_1(doubleOopPrimitives::hyperbolicSine, oop receiver) {
00164   PROLOGUE_1("hyperbolicSine", receiver);
00165   ASSERT_RECEIVER;
00166   return new_double(sinh(doubleOop(receiver)->value()));
00167 }
00168 
00169 PRIM_DECL_1(doubleOopPrimitives::hyperbolicTangent, oop receiver) {
00170   PROLOGUE_1("hyperbolicTangent", receiver);
00171   ASSERT_RECEIVER;
00172   return new_double(tanh(doubleOop(receiver)->value()));
00173 }
00174 
00175 PRIM_DECL_1(doubleOopPrimitives::sqrt, oop receiver) {
00176   PROLOGUE_1("sqrt", receiver);
00177   ASSERT_RECEIVER;
00178   return new_double(::sqrt(doubleOop(receiver)->value()));
00179 }
00180 
00181 PRIM_DECL_1(doubleOopPrimitives::squared, oop receiver) {
00182   PROLOGUE_1("squared", receiver);
00183   ASSERT_RECEIVER;
00184   return new_double(doubleOop(receiver)->value() * 2);
00185 }
00186 
00187 PRIM_DECL_1(doubleOopPrimitives::ln, oop receiver) {
00188   PROLOGUE_1("ln", receiver);
00189   ASSERT_RECEIVER;
00190   return new_double(log(doubleOop(receiver)->value()));
00191 }
00192 
00193 PRIM_DECL_1(doubleOopPrimitives::exp, oop receiver) {
00194   PROLOGUE_1("exp", receiver);
00195   ASSERT_RECEIVER;
00196   return new_double(::exp(doubleOop(receiver)->value()));
00197 }
00198 
00199 PRIM_DECL_1(doubleOopPrimitives::log10, oop receiver) {
00200   PROLOGUE_1("log10", receiver);
00201   ASSERT_RECEIVER;
00202   return new_double(::log10(doubleOop(receiver)->value()));
00203 }
00204 
00205 PRIM_DECL_1(doubleOopPrimitives::isNan, oop receiver) {
00206   PROLOGUE_1("isNan", receiver);
00207   ASSERT_RECEIVER;
00208   return _isnan(doubleOop(receiver)->value()) ? trueObj : falseObj;
00209 }
00210 
00211 PRIM_DECL_1(doubleOopPrimitives::isFinite, oop receiver) {
00212   PROLOGUE_1("isFinite", receiver);
00213   ASSERT_RECEIVER;
00214   return _finite(doubleOop(receiver)->value()) ? trueObj : falseObj;
00215 }
00216 
00217 PRIM_DECL_1(doubleOopPrimitives::floor, oop receiver) {
00218   PROLOGUE_1("floor", receiver);
00219   ASSERT_RECEIVER;
00220   double result = ::floor(doubleOop(receiver)->value());
00221   return new_double(result);
00222 }
00223 
00224 PRIM_DECL_1(doubleOopPrimitives::smi_floor, oop receiver) {
00225   PROLOGUE_1("floor", receiver);
00226   ASSERT_RECEIVER;
00227   double result = ::floor(doubleOop(receiver)->value());
00228   if (result < 0.0) {
00229     if (result > smi_min) return as_smiOop((int) result);
00230   } else {
00231     if (result < smi_max) return as_smiOop((int) result);
00232   }
00233   return markSymbol(vmSymbols::conversion_failed());
00234 
00235 }
00236 
00237 PRIM_DECL_1(doubleOopPrimitives::ceiling, oop receiver) {
00238   PROLOGUE_1("ceiling", receiver);
00239   ASSERT_RECEIVER;
00240   double result = ceil(doubleOop(receiver)->value());
00241   return new_double(result);
00242 }
00243 
00244 PRIM_DECL_1(doubleOopPrimitives::exponent, oop receiver) {
00245   PROLOGUE_1("exponent", receiver);
00246   ASSERT_RECEIVER;
00247   int result;
00248   (void) frexp(doubleOop(receiver)->value(), &result);
00249   return as_smiOop(result);
00250 }
00251 
00252 PRIM_DECL_1(doubleOopPrimitives::mantissa, oop receiver) {
00253   PROLOGUE_1("mantissa", receiver);
00254   ASSERT_RECEIVER;
00255   int exp;
00256   return new_double(frexp(doubleOop(receiver)->value(), &exp));
00257 }
00258 
00259 PRIM_DECL_1(doubleOopPrimitives::truncated, oop receiver) {
00260   PROLOGUE_1("truncated", receiver);
00261   ASSERT_RECEIVER;
00262   double value = doubleOop(receiver)->value();
00263   return new_double(value > 0.0 ? ::floor(value) : ::ceil(value));
00264 }
00265 
00266 PRIM_DECL_2(doubleOopPrimitives::timesTwoPower, oop receiver, oop argument) {
00267   PROLOGUE_2("timesTwoPower", receiver, argument)
00268   ASSERT_RECEIVER;
00269   if (!argument->is_smi())
00270     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00271   return new_double(ldexp(doubleOop(receiver)->value(), smiOop(argument)->value()));
00272 }
00273 
00274 PRIM_DECL_1(doubleOopPrimitives::roundedAsSmallInteger, oop receiver) {
00275   PROLOGUE_1("roundedAsSmallInteger", receiver);
00276   ASSERT_RECEIVER;
00277   if (doubleOop(receiver)->value() < 0.0) {
00278     double result = ::ceil(doubleOop(receiver)->value() - 0.5);
00279     if (result > smi_min)
00280         return as_smiOop((int) result);
00281   } else {
00282     double result = ::floor(doubleOop(receiver)->value() + 0.5);
00283     if (result < smi_max)
00284          return as_smiOop((int) result);
00285   }
00286   return markSymbol(vmSymbols::smi_conversion_failed());
00287 }
00288 
00289 PRIM_DECL_1(doubleOopPrimitives::asSmallInteger, oop receiver) {
00290   PROLOGUE_1("asSmallInteger", receiver);
00291   ASSERT_RECEIVER;
00292   double value = doubleOop(receiver)->value();
00293   if (value != ::floor(value)) 
00294     return markSymbol(vmSymbols::smi_conversion_failed());
00295   if (value < 0.0) {
00296     if (value > smi_min)
00297         return as_smiOop((int) value);
00298   } else {
00299     if (value < smi_max)
00300          return as_smiOop((int) value);
00301   }
00302   return markSymbol(vmSymbols::smi_conversion_failed());
00303 }
00304 
00305 
00306 PRIM_DECL_2(doubleOopPrimitives::printFormat, oop receiver, oop argument) {
00307   PROLOGUE_2("printFormat", receiver, argument);
00308   ASSERT_RECEIVER;
00309   const int size = 100;
00310   char format[size];
00311   
00312   if (argument->is_byteArray()) {
00313     byteArrayOop(argument)->copy_null_terminated(format, size);
00314   } else if (argument->is_doubleByteArray()) {
00315     doubleByteArrayOop(argument)->copy_null_terminated(format, size);
00316   } else {
00317     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00318   }
00319   lprintf(format, doubleOop(receiver)->value());
00320   return receiver;
00321 }
00322 
00323 PRIM_DECL_1(doubleOopPrimitives::printString, oop receiver) {
00324   PROLOGUE_1("printString", receiver);
00325   ASSERT_RECEIVER;
00326   ResourceMark rm;
00327   char* result = NEW_RESOURCE_ARRAY(char, 4*K);
00328   int len = sprintf(result, "%1.6f", doubleOop(receiver)->value());
00329   while (len > 1 && result[len-1] == '0' && result[len-2] != '.') len--;
00330   result[len] = '\0';
00331 
00332   BlockScavenge bs;
00333   byteArrayOop ba = oopFactory::new_byteArray(len);
00334   for (int i = 0; i < len; i++) {
00335     ba->byte_at_put(i+1, result[i]);
00336   }
00337   return ba;
00338 }
00339 
00340 PRIM_DECL_0(doubleOopPrimitives::max_value) {
00341   PROLOGUE_0("max_value");
00342   return new_double(DBL_MAX);
00343 }
00344 
00345 PRIM_DECL_0(doubleOopPrimitives::min_positive_value) {
00346   PROLOGUE_0("min_positive_value");
00347   return new_double(DBL_MIN);
00348 }
00349 
00350 PRIM_DECL_1(doubleOopPrimitives::store_string, oop receiver) {
00351   PROLOGUE_1("printFormat", receiver);
00352   ASSERT_RECEIVER;
00353   BlockScavenge bs;
00354 
00355   double value = doubleOop(receiver)->value();
00356   u_char* addr = (u_char*) &value;
00357 
00358   byteArrayOop result = oopFactory::new_byteArray(8);
00359   for (int index = 0; index < 8; index++) {
00360     result->byte_at_put(index+1, addr[index]); 
00361   }
00362   return result;
00363 }
00364 
00365 PRIM_DECL_3(doubleOopPrimitives::mandelbrot, oop re, oop im, oop n) {
00366   PROLOGUE_3("mandelbrot", re, im, n);
00367 
00368   if (!re->is_double()) return markSymbol(vmSymbols::first_argument_has_wrong_type ());
00369   if (!im->is_double()) return markSymbol(vmSymbols::second_argument_has_wrong_type());
00370   if (!n ->is_smi   ()) return markSymbol(vmSymbols::third_argument_has_wrong_type ());
00371   
00372   double c_re = doubleOop(re)->value();
00373   double c_im = doubleOop(im)->value();
00374   double z_re = c_re;
00375   double z_im = c_im;
00376   double d_re = z_re * z_re;
00377   double d_im = z_im * z_im;
00378 
00379   int i    = 0;
00380   int imax = smiOop(n)->value() - 1;
00381   
00382   while (i < imax && d_re + d_im <= 4.0) {
00383     z_im = 2.0 * z_re * z_im + c_im;
00384     z_re = d_re - d_im + c_re;
00385     d_re = z_re * z_re;
00386     d_im = z_im * z_im;
00387     i++;
00388   }
00389 
00390   return as_smiOop(i);
00391 }

Generated on Mon Oct 9 13:37:08 2006 for Strongtalk VM by  doxygen 1.4.7