00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
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 }