int main(){ long long x,y,l,r,t=0,f,ls,rs; scanf("%I64d%I64d%I64d%I64d",&x,&y,&l,&r); y=lmin(y,x*2-1); ls=l/x; rs=r/x; if(l<x)l=x; if(r<l){ puts("0"); return 0; } if(x==y){ t=(r-l)/x; if(l%x==0&&r%x==0)t++; printf("%I64d",t); return 0; } if(ls==rs){ printf("%I64d",z(lmin(r,rs*y))-l+1); return 0; } f=(2*x-y-1)/(y-x); if((2*x-y-1)%(y-x)==0)f++; if(ls<f)t+=(1+(y-x)*ls+1+(y-x)*lmin(f-1,rs))*(lmin(f,rs+1)-ls)/2; if(rs>=f)t+=x*(rs-f+1); if(l/y<rs)t-=z(l-ls*x+1); else t-=z(rs*y-ls*x+1); if((rs+1)*x-1/y<rs)t-=z((rs+1)*x-1-r); else t-=z(rs*y-r); printf("%I64d",t); return 0; }
void Speed::fix(AIHTTPTimeoutPolicy* policy) { bool changed = false; if (policy->mLowSpeedTime > ABS_max_low_speed_time) { policy->mLowSpeedTime = ABS_max_low_speed_time; changed = true; } else if (policy->mLowSpeedTime != 0 && policy->mLowSpeedTime < min()) { policy->mLowSpeedTime = min(); changed = true; } if (changed) { // Transaction limits depend on Speed time. Transaction::fix(policy); } if (policy->mLowSpeedTime > max(policy)) { policy->mLowSpeedTime = max(policy); } if (policy->mLowSpeedLimit > lmax()) { policy->mLowSpeedLimit = lmax(); } else if (policy->mLowSpeedLimit != 0 && policy->mLowSpeedLimit < lmin()) { policy->mLowSpeedLimit = lmin(); } }
/*** redraw - Mark a range of lines in file dirty * * Marks a range of lines in a file as needing to be updated. Each window that * they occur in is marked. * * Input: * pFile = File handle containing dirty lines * linFirst, linLast = Range of lines to mark * * Output: * Returns nothing * *************************************************************************/ void redraw ( PFILE pFile, LINE linFirst, LINE linLast ) { LINE linFirstUpd, linLastUpd; REGISTER PINS pInsTmp; int iWinTmp; REGISTER struct windowType *pWinTmp; if (linFirst > linLast) { linFirstUpd = linLast; linLast = linFirst; linFirst = linFirstUpd; } for (iWinTmp = 0, pWinTmp = WinList; iWinTmp < cWin; iWinTmp++, pWinTmp++) { if (pWinTmp->pInstance) { if (pFile == pWinTmp->pInstance->pFile) { pInsTmp = pWinTmp->pInstance; linFirstUpd = WINYPOS(pWinTmp) + lmax (0L, linFirst-YWIN(pInsTmp)-1); linLastUpd = WINYPOS(pWinTmp) + lmin ((long) (WINYSIZE(pWinTmp) - 1), linLast - YWIN(pInsTmp)); while (linFirstUpd <= linLastUpd) { SETFLAG (fChange[linFirstUpd++],FMODIFY); } } } } SETFLAG (fDisplay, RTEXT); }
eqveqv(int nvarno, int ovarno, ftnint delta) #endif { register struct Equivblock *neweqv, *oldeqv; register Namep np; struct Eqvchain *q, *q1; neweqv = eqvclass + nvarno; oldeqv = eqvclass + ovarno; neweqv->eqvbottom = lmin(neweqv->eqvbottom, oldeqv->eqvbottom - delta); neweqv->eqvtop = lmax(neweqv->eqvtop, oldeqv->eqvtop - delta); oldeqv->eqvbottom = oldeqv->eqvtop = 0; for(q = oldeqv->equivs ; q ; q = q1) { q1 = q->eqvnextp; if( (np = q->eqvitem.eqvname) && np->vardesc.varno==ovarno) { q->eqvnextp = neweqv->equivs; neweqv->equivs = q; q->eqvoffset += delta; np->vardesc.varno = nvarno; np->voffset -= delta; } else free( (charptr) q); } oldeqv->equivs = NULL; }
static int in6_mtuexpire(struct radix_node *rn, void *rock) { struct rtentry *rt = (struct rtentry *)rn; struct mtuex_arg *ap = rock; struct timeval timenow; getmicrotime(&timenow); /* sanity */ if (!rt) panic("rt == NULL in in6_mtuexpire"); RT_LOCK(rt); if (rt->rt_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_rmx.rmx_expire <= timenow.tv_sec) { rt->rt_flags |= RTF_PROBEMTU; } else { ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } RT_UNLOCK(rt); return 0; }
void Map::getMinMaxCoordinates(ExactModelCoordinate& min, ExactModelCoordinate& max) { if (m_layers.empty()) { return; } std::list<Layer*>::iterator it = m_layers.begin(); Layer* layer = *it; for (; it != m_layers.end(); ++it) { ModelCoordinate newMin, newMax; (*it)->getMinMaxCoordinates(newMin, newMax, layer); if (newMin.x < min.x) { min.x = newMin.x; } if (newMax.x > max.x) { max.x = newMax.x; } if (newMin.y < min.y) { min.y = newMin.y; } if (newMax.y > max.y) { max.y = newMax.y; } } Location lmin(layer); Location lmax(layer); lmin.setExactLayerCoordinates(min); lmax.setExactLayerCoordinates(max); min = lmin.getMapCoordinates(); max = lmax.getMapCoordinates(); }
/* * Get rid of old routes. When draining, this deletes everything, even when * the timeout is not expired yet. When updating, this makes sure that * nothing has a timeout longer than the current value of rtq_reallyold. */ static int in6_rtqkill(struct radix_node *rn, void *rock) { struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; if (rt->rt_flags & RTPRF_OURS) { ap->found++; if (ap->draining || rt->rt_rmx.rmx_expire <= time_second) { if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL); if (err) log(LOG_WARNING, "in6_rtqkill: error %d", err); else ap->killed++; } else { if (ap->updating && (rt->rt_rmx.rmx_expire - time_second > rtq_reallyold)) { rt->rt_rmx.rmx_expire = time_second + rtq_reallyold; } ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0; }
/* Function to process an ack. */ void tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) { /* * RFC 3465 - Appropriate Byte Counting. * * If the window is currently less than ssthresh, * open the window by the number of bytes ACKed by * the last ACK, however clamp the window increase * to an upper limit "L". * * In congestion avoidance phase, open the window by * one segment each time "bytes_acked" grows to be * greater than or equal to the congestion window. */ u_int cw = tp->snd_cwnd; u_int incr = tp->t_maxseg; int acked = 0; acked = BYTES_ACKED(th, tp); if (tcp_do_rfc3465) { if (cw >= tp->snd_ssthresh) { tp->t_bytes_acked += acked; if (tp->t_bytes_acked >= cw) { /* Time to increase the window. */ tp->t_bytes_acked -= cw; } else { /* No need to increase yet. */ incr = 0; } } else { /* * If the user explicitly enables RFC3465 * use 2*SMSS for the "L" param. Otherwise * use the more conservative 1*SMSS. * * (See RFC 3465 2.3 Choosing the Limit) */ uint32_t abc_lim; abc_lim = (tcp_do_rfc3465_lim2 && tp->snd_nxt == tp->snd_max) ? incr * 2 : incr; incr = lmin(acked, abc_lim); } } else { /* * If the window gives us less than ssthresh packets * in flight, open exponentially (segsz per packet). * Otherwise open linearly: segsz per window * (segsz^2 / cwnd per packet). */ if (cw >= tp->snd_ssthresh) incr = max((incr * incr / cw), 1); } tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale); }
/** * Initiate a get operation. * * @param btl (IN) BTL module * @param endpoint (IN) BTL addressing information * @param descriptor (IN) Description of the data to be transferred */ int mca_btl_scif_get (struct mca_btl_base_module_t *btl, struct mca_btl_base_endpoint_t *endpoint, struct mca_btl_base_descriptor_t *des) { mca_btl_scif_segment_t *src = (mca_btl_scif_segment_t *) des->des_src; mca_btl_scif_segment_t *dst = (mca_btl_scif_segment_t *) des->des_dst; size_t len = lmin (src->base.seg_len, dst->base.seg_len); int rc, mark, flags = 0; off_t roffset, loffset; size_t to_get; #if defined(SCIF_TIMING) struct timespec ts; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); mca_btl_scif_component.get_count++; #endif BTL_VERBOSE(("Using DMA Get for frag %p from offset %lu", (void *) des, (unsigned long) src->scif_offset)); roffset = src->scif_offset + (off_t)(src->orig_ptr - src->base.seg_addr.lval); loffset = dst->scif_offset + (off_t)(dst->orig_ptr - dst->base.seg_addr.lval); if (mca_btl_scif_component.rma_use_cpu) { flags = SCIF_RMA_USECPU; } if (mca_btl_scif_component.rma_sync) { flags |= SCIF_RMA_SYNC; } /* start the read */ rc = scif_readfrom (endpoint->scif_epd, loffset, len, roffset, flags); if (OPAL_UNLIKELY(-1 == rc)) { return OMPI_ERROR; } /* always call the callback function */ des->des_flags |= MCA_BTL_DES_SEND_ALWAYS_CALLBACK; if (!(flags & SCIF_RMA_SYNC)) { /* according to the scif documentation is is better to use a fence rather * than using the SCIF_RMA_SYNC flag with scif_readfrom */ scif_fence_mark (endpoint->scif_epd, SCIF_FENCE_INIT_SELF, &mark); scif_fence_wait (endpoint->scif_epd, mark); } #if defined(SCIF_TIMING) SCIF_UPDATE_TIMER(mca_btl_scif_component.get_time, mca_btl_scif_component.get_time_max, ts); #endif /* since we completed the fence the RMA operation is complete */ mca_btl_scif_frag_complete ((mca_btl_scif_base_frag_t *) des, OMPI_SUCCESS); return OMPI_SUCCESS; }
/* * Get rid of old routes. When draining, this deletes everything, even when * the timeout is not expired yet. This also applies if the route is dynamic * and there are sufficiently large number of such routes (more than a half of * maximum). When updating, this makes sure that nothing has a timeout longer * than the current value of rtq_reallyold. */ static int in6_rtqkill(struct radix_node *rn, void *rock) { struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; struct timeval timenow; getmicrotime(&timenow); lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED); RT_LOCK(rt); if (rt->rt_flags & RTPRF_OURS) { ap->found++; if (ap->draining || rt->rt_rmx.rmx_expire <= timenow.tv_sec || ((rt->rt_flags & RTF_DYNAMIC) != 0 && ip6_maxdynroutes >= 0 && in6dynroutes > ip6_maxdynroutes / 2)) { if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); /* * Delete this route since we're done with it; * the route may be freed afterwards, so we * can no longer refer to 'rt' upon returning * from rtrequest(). Safe to drop rt_lock and * use rt_key, rt_gateway, since holding rnh_lock * here prevents another thread from calling * rt_setgate() on this route. */ RT_UNLOCK(rt); err = rtrequest_locked(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if (err) { log(LOG_WARNING, "in6_rtqkill: error %d", err); } else { ap->killed++; } } else { if (ap->updating && (rt->rt_rmx.rmx_expire - timenow.tv_sec > rtq_reallyold)) { rt->rt_rmx.rmx_expire = timenow.tv_sec + rtq_reallyold; } ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); RT_UNLOCK(rt); } } else { RT_UNLOCK(rt); } return 0; }
static int in6_mtuexpire(struct rtentry *rt, void *rock) { struct mtuex_arg *ap = rock; if (rt->rt_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_expire <= time_uptime) { rt->rt_flags |= RTF_PROBEMTU; } else { ap->nextstop = lmin(ap->nextstop, rt->rt_expire); } } return (0); }
/* Function to process an ack. */ void tcp_ledbat_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) { /* * RFC 3465 - Appropriate Byte Counting. * * If the window is currently less than ssthresh, * open the window by the number of bytes ACKed by * the last ACK, however clamp the window increase * to an upper limit "L". * * In congestion avoidance phase, open the window by * one segment each time "bytes_acked" grows to be * greater than or equal to the congestion window. */ register u_int cw = tp->snd_cwnd; register u_int incr = tp->t_maxseg; int acked = 0; acked = BYTES_ACKED(th, tp); tp->t_bytes_acked += acked; if (cw >= tp->bg_ssthresh) { /* congestion-avoidance */ if (tp->t_bytes_acked < cw) { /* No need to increase yet. */ incr = 0; } } else { /* * If the user explicitly enables RFC3465 * use 2*SMSS for the "L" param. Otherwise * use the more conservative 1*SMSS. * * (See RFC 3465 2.3 Choosing the Limit) */ u_int abc_lim; abc_lim = (tcp_do_rfc3465_lim2 && tp->snd_nxt == tp->snd_max) ? incr * 2 : incr; incr = lmin(acked, abc_lim); } if (tp->t_bytes_acked >= cw) tp->t_bytes_acked -= cw; if (incr > 0) update_cwnd(tp, incr); }
/* * Get rid of old routes. When draining, this deletes everything, even when * the timeout is not expired yet. When updating, this makes sure that * nothing has a timeout longer than the current value of rtq_reallyold. */ static int in_rtqkill(struct radix_node *rn, void *rock) { struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; struct timeval timenow; getmicrotime(&timenow); lck_mtx_assert(rt_mtx, LCK_MTX_ASSERT_OWNED); if (rt->rt_flags & RTPRF_OURS) { ap->found++; if (ap->draining || rt->rt_rmx.rmx_expire <= timenow.tv_sec) { if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); err = rtrequest_locked(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if (err) { log(LOG_WARNING, "in_rtqkill: error %d\n", err); } else { ap->killed++; } } else { if (ap->updating && (rt->rt_rmx.rmx_expire - timenow.tv_sec > rtq_reallyold)) { rt->rt_rmx.rmx_expire = timenow.tv_sec + rtq_reallyold; } ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0; }
static int in6_mtuexpire(struct radix_node *rn, void *rock) { struct rtentry *rt = (struct rtentry *)rn; struct mtuex_arg *ap = rock; /* sanity */ if (!rt) panic("rt == NULL in in6_mtuexpire"); if (rt->rt_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) { if (rt->rt_rmx.rmx_expire <= time_second) { rt->rt_flags |= RTF_PROBEMTU; } else { ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0; }
/* * Get rid of old routes. When draining, this deletes everything, even when * the timeout is not expired yet. When updating, this makes sure that * nothing has a timeout longer than the current value of rtq_reallyold. */ static int in_rtqkill(struct radix_node *rn, void *rock) { struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh); if (rt->rt_flags & RTPRF_OURS) { ap->found++; if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) { if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); err = in_rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags | RTF_RNH_LOCKED, 0, rt->rt_fibnum); if (err) { log(LOG_WARNING, "in_rtqkill: error %d\n", err); } else { ap->killed++; } } else { if (ap->updating && (rt->rt_rmx.rmx_expire - time_uptime > V_rtq_reallyold)) { rt->rt_rmx.rmx_expire = time_uptime + V_rtq_reallyold; } ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0; }
/* * Get rid of old routes. When draining, this deletes everything, even when * the timeout is not expired yet. When updating, this makes sure that * nothing has a timeout longer than the current value of rtq_reallyold. */ static int in_rtqkill(struct radix_node *rn, void *rock) { struct rtqk_arg *ap = rock; struct rtentry *rt = (struct rtentry *)rn; int err; if(rt->rt_flags & RTPRF_OURS) { ap->found++; if(ap->draining || rt->rt_rmx.rmx_expire <= rtems_bsdnet_seconds_since_boot()) { if(rt->rt_refcnt > 0) panic("rtqkill route really not free"); err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); if(err) { log(LOG_WARNING, "in_rtqkill: error %d\n", err); } else { ap->killed++; } } else { if(ap->updating && (rt->rt_rmx.rmx_expire - rtems_bsdnet_seconds_since_boot() > rtq_reallyold)) { rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot() + rtq_reallyold; } ap->nextstop = lmin(ap->nextstop, rt->rt_rmx.rmx_expire); } } return 0; }
/* * Tcp output routine: figure out what should be sent and send it. */ int tcp_output(struct tcpcb *tp) { struct socket *so = tp->t_inpcb->inp_socket; long len, recwin, sendwin; int off, flags, error; #ifdef TCP_SIGNATURE int sigoff = 0; #endif struct mbuf *m; struct ip *ip = NULL; struct ipovly *ipov = NULL; struct tcphdr *th; u_char opt[TCP_MAXOLEN]; unsigned ipoptlen, optlen, hdrlen; int idle, sendalot; int i, sack_rxmit; int sack_bytes_rxmt; struct sackhole *p; #if 0 int maxburst = TCP_MAXBURST; #endif struct rmxp_tao tao; #ifdef INET6 struct ip6_hdr *ip6 = NULL; int isipv6; bzero(&tao, sizeof(tao)); isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0; #endif #ifdef TCP_ECN int needect; #endif INP_LOCK_ASSERT(tp->t_inpcb); /* * Determine length of data that should be transmitted, * and flags that will be used. * If there is some data or critical controls (SYN, RST) * to send, then transmit; otherwise, investigate further. */ idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una); if (idle && (ticks - tp->t_rcvtime) >= tp->t_rxtcur) { /* * We have been idle for "a while" and no acks are * expected to clock out any data we send -- * slow start to get ack "clock" running again. * * Set the slow-start flight size depending on whether * this is a local network or not. */ int ss = ss_fltsz; #ifdef INET6 if (isipv6) { if (in6_localaddr(&tp->t_inpcb->in6p_faddr)) ss = ss_fltsz_local; } else #endif if (in_localaddr(tp->t_inpcb->inp_faddr)) ss = ss_fltsz_local; tp->snd_cwnd = tp->t_maxseg * ss; } tp->t_flags &= ~TF_LASTIDLE; if (idle) { if (tp->t_flags & TF_MORETOCOME) { tp->t_flags |= TF_LASTIDLE; idle = 0; } } again: /* * If we've recently taken a timeout, snd_max will be greater than * snd_nxt. There may be SACK information that allows us to avoid * resending already delivered data. Adjust snd_nxt accordingly. */ if (tp->sack_enable && SEQ_LT(tp->snd_nxt, tp->snd_max)) tcp_sack_adjust(tp); sendalot = 0; off = tp->snd_nxt - tp->snd_una; sendwin = min(tp->snd_wnd, tp->snd_cwnd); sendwin = min(sendwin, tp->snd_bwnd); flags = tcp_outflags[tp->t_state]; /* * Send any SACK-generated retransmissions. If we're explicitly trying * to send out new data (when sendalot is 1), bypass this function. * If we retransmit in fast recovery mode, decrement snd_cwnd, since * we're replacing a (future) new transmission with a retransmission * now, and we previously incremented snd_cwnd in tcp_input(). */ /* * Still in sack recovery , reset rxmit flag to zero. */ sack_rxmit = 0; sack_bytes_rxmt = 0; len = 0; p = NULL; if (tp->sack_enable && IN_FASTRECOVERY(tp) && (p = tcp_sack_output(tp, &sack_bytes_rxmt))) { long cwin; cwin = min(tp->snd_wnd, tp->snd_cwnd) - sack_bytes_rxmt; if (cwin < 0) cwin = 0; /* Do not retransmit SACK segments beyond snd_recover */ if (SEQ_GT(p->end, tp->snd_recover)) { /* * (At least) part of sack hole extends beyond * snd_recover. Check to see if we can rexmit data * for this hole. */ if (SEQ_GEQ(p->rxmit, tp->snd_recover)) { /* * Can't rexmit any more data for this hole. * That data will be rexmitted in the next * sack recovery episode, when snd_recover * moves past p->rxmit. */ p = NULL; goto after_sack_rexmit; } else /* Can rexmit part of the current hole */ len = ((long)ulmin(cwin, tp->snd_recover - p->rxmit)); } else len = ((long)ulmin(cwin, p->end - p->rxmit)); off = p->rxmit - tp->snd_una; KASSERT(off >= 0,("%s: sack block to the left of una : %d", __func__, off)); if (len > 0) { sack_rxmit = 1; sendalot = 1; tcpstat.tcps_sack_rexmits++; tcpstat.tcps_sack_rexmit_bytes += min(len, tp->t_maxseg); } } after_sack_rexmit: /* * Get standard flags, and add SYN or FIN if requested by 'hidden' * state flags. */ if (tp->t_flags & TF_NEEDFIN) flags |= TH_FIN; if (tp->t_flags & TF_NEEDSYN) flags |= TH_SYN; SOCKBUF_LOCK(&so->so_snd); /* * If in persist timeout with window of 0, send 1 byte. * Otherwise, if window is small but nonzero * and timer expired, we will send what we can * and go to transmit state. */ if (tp->t_force) { if (sendwin == 0) { /* * If we still have some data to send, then * clear the FIN bit. Usually this would * happen below when it realizes that we * aren't sending all the data. However, * if we have exactly 1 byte of unsent data, * then it won't clear the FIN bit below, * and if we are in persist state, we wind * up sending the packet without recording * that we sent the FIN bit. * * We can't just blindly clear the FIN bit, * because if we don't have any more data * to send then the probe will be the FIN * itself. */ if (off < so->so_snd.sb_cc) flags &= ~TH_FIN; sendwin = 1; } else { callout_stop(tp->tt_persist); tp->t_rxtshift = 0; } } /* * If snd_nxt == snd_max and we have transmitted a FIN, the * offset will be > 0 even if so_snd.sb_cc is 0, resulting in * a negative length. This can also occur when TCP opens up * its congestion window while receiving additional duplicate * acks after fast-retransmit because TCP will reset snd_nxt * to snd_max after the fast-retransmit. * * In the normal retransmit-FIN-only case, however, snd_nxt will * be set to snd_una, the offset will be 0, and the length may * wind up 0. * * If sack_rxmit is true we are retransmitting from the scoreboard * in which case len is already set. */ if (sack_rxmit == 0) { if (sack_bytes_rxmt == 0) len = ((long)ulmin(so->so_snd.sb_cc, sendwin) - off); else { long cwin; /* * We are inside of a SACK recovery episode and are * sending new data, having retransmitted all the * data possible in the scoreboard. */ len = ((long)ulmin(so->so_snd.sb_cc, tp->snd_wnd) - off); /* * Don't remove this (len > 0) check ! * We explicitly check for len > 0 here (although it * isn't really necessary), to work around a gcc * optimization issue - to force gcc to compute * len above. Without this check, the computation * of len is bungled by the optimizer. */ if (len > 0) { cwin = tp->snd_cwnd - (tp->snd_nxt - tp->sack_newdata) - sack_bytes_rxmt; if (cwin < 0) cwin = 0; len = lmin(len, cwin); } } } /* * Lop off SYN bit if it has already been sent. However, if this * is SYN-SENT state and if segment contains data and if we don't * know that foreign host supports TAO, suppress sending segment. */ if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) { flags &= ~TH_SYN; off--, len++; if (tcp_do_rfc1644) tcp_hc_gettao(&tp->t_inpcb->inp_inc, &tao); if (len > 0 && tp->t_state == TCPS_SYN_SENT && tao.tao_ccsent == 0) goto just_return; } /* * Be careful not to send data and/or FIN on SYN segments * in cases when no CC option will be sent. * This measure is needed to prevent interoperability problems * with not fully conformant TCP implementations. */ if ((flags & TH_SYN) && ((tp->t_flags & TF_NOOPT) || !(tp->t_flags & TF_REQ_CC) || ((flags & TH_ACK) && !(tp->t_flags & TF_RCVD_CC)))) { len = 0; flags &= ~TH_FIN; } if (len < 0) { /* * If FIN has been sent but not acked, * but we haven't been called to retransmit, * len will be < 0. Otherwise, window shrank * after we sent into it. If window shrank to 0, * cancel pending retransmit, pull snd_nxt back * to (closed) window, and set the persist timer * if it isn't already going. If the window didn't * close completely, just wait for an ACK. */ len = 0; if (sendwin == 0) { callout_stop(tp->tt_rexmt); tp->t_rxtshift = 0; tp->snd_nxt = tp->snd_una; if (!callout_active(tp->tt_persist)) tcp_setpersist(tp); } } /* * len will be >= 0 after this point. Truncate to the maximum * segment length and ensure that FIN is removed if the length * no longer contains the last data byte. */ if (len > tp->t_maxseg) { len = tp->t_maxseg; sendalot = 1; } if (sack_rxmit) { if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc)) flags &= ~TH_FIN; } else { if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) flags &= ~TH_FIN; } recwin = sbspace(&so->so_rcv); /* * Sender silly window avoidance. We transmit under the following * conditions when len is non-zero: * * - We have a full segment * - This is the last buffer in a write()/send() and we are * either idle or running NODELAY * - we've timed out (e.g. persist timer) * - we have more then 1/2 the maximum send window's worth of * data (receiver may be limited the window size) * - we need to retransmit */ if (len) { if (len == tp->t_maxseg) goto send; /* * NOTE! on localhost connections an 'ack' from the remote * end may occur synchronously with the output and cause * us to flush a buffer queued with moretocome. XXX * * note: the len + off check is almost certainly unnecessary. */ if (!(tp->t_flags & TF_MORETOCOME) && /* normal case */ (idle || (tp->t_flags & TF_NODELAY)) && len + off >= so->so_snd.sb_cc && (tp->t_flags & TF_NOPUSH) == 0) { goto send; } if (tp->t_force) /* typ. timeout case */ goto send; if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) goto send; if (SEQ_LT(tp->snd_nxt, tp->snd_max)) /* retransmit case */ goto send; if (sack_rxmit) goto send; } /* * Compare available window to amount of window * known to peer (as advertised window less * next expected input). If the difference is at least two * max size segments, or at least 50% of the maximum possible * window, then want to send a window update to peer. * Skip this if the connection is in T/TCP half-open state. */ if (recwin > 0 && !(tp->t_flags & TF_NEEDSYN)) { /* * "adv" is the amount we can increase the window, * taking into account that we are limited by * TCP_MAXWIN << tp->rcv_scale. */ long adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale) - (tp->rcv_adv - tp->rcv_nxt); if (adv >= (long) (2 * tp->t_maxseg)) goto send; if (2 * adv >= (long) so->so_rcv.sb_hiwat) goto send; } /* * Send if we owe the peer an ACK, RST, SYN, or urgent data. ACKNOW * is also a catch-all for the retransmit timer timeout case. */ if (tp->t_flags & TF_ACKNOW) goto send; if ((flags & TH_RST) || ((flags & TH_SYN) && (tp->t_flags & TF_NEEDSYN) == 0)) goto send; if (SEQ_GT(tp->snd_up, tp->snd_una)) goto send; /* * If our state indicates that FIN should be sent * and we have not yet done so, then we need to send. */ if (flags & TH_FIN && ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) goto send; /* * In SACK, it is possible for tcp_output to fail to send a segment * after the retransmission timer has been turned off. Make sure * that the retransmission timer is set. */ if (tp->sack_enable && SEQ_GT(tp->snd_max, tp->snd_una) && !callout_active(tp->tt_rexmt) && !callout_active(tp->tt_persist)) { callout_reset(tp->tt_rexmt, tp->t_rxtcur, tcp_timer_rexmt, tp); goto just_return; } /* * TCP window updates are not reliable, rather a polling protocol * using ``persist'' packets is used to insure receipt of window * updates. The three ``states'' for the output side are: * idle not doing retransmits or persists * persisting to move a small or zero window * (re)transmitting and thereby not persisting * * callout_active(tp->tt_persist) * is true when we are in persist state. * tp->t_force * is set when we are called to send a persist packet. * callout_active(tp->tt_rexmt) * is set when we are retransmitting * The output side is idle when both timers are zero. * * If send window is too small, there is data to transmit, and no * retransmit or persist is pending, then go to persist state. * If nothing happens soon, send when timer expires: * if window is nonzero, transmit what we can, * otherwise force out a byte. */ if (so->so_snd.sb_cc && !callout_active(tp->tt_rexmt) && !callout_active(tp->tt_persist)) { tp->t_rxtshift = 0; tcp_setpersist(tp); } /* * No reason to send a segment, just return. */ just_return: SOCKBUF_UNLOCK(&so->so_snd); return (0); send: SOCKBUF_LOCK_ASSERT(&so->so_snd); /* * Before ESTABLISHED, force sending of initial options * unless TCP set not to do any options. * NOTE: we assume that the IP/TCP header plus TCP options * always fit in a single mbuf, leaving room for a maximum * link header, i.e. * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MCLBYTES */ optlen = 0; #ifdef INET6 if (isipv6) hdrlen = sizeof (struct ip6_hdr) + sizeof (struct tcphdr); else #endif hdrlen = sizeof (struct tcpiphdr); if (flags & TH_SYN) { tp->snd_nxt = tp->iss; if ((tp->t_flags & TF_NOOPT) == 0) { u_short mss; opt[0] = TCPOPT_MAXSEG; opt[1] = TCPOLEN_MAXSEG; mss = htons((u_short) tcp_mssopt(&tp->t_inpcb->inp_inc)); (void)memcpy(opt + 2, &mss, sizeof(mss)); optlen = TCPOLEN_MAXSEG; /* * If this is the first SYN of connection (not a SYN * ACK), include SACK_PERMIT_HDR option. If this is a * SYN ACK, include SACK_PERMIT_HDR option if peer has * already done so. This is only for active connect, * since the syncache takes care of the passive connect. */ if (tp->sack_enable && ((flags & TH_ACK) == 0 || (tp->t_flags & TF_SACK_PERMIT))) { *((u_int32_t *) (opt + optlen)) = htonl(TCPOPT_SACK_PERMIT_HDR); optlen += 4; } if ((tp->t_flags & TF_REQ_SCALE) && ((flags & TH_ACK) == 0 || (tp->t_flags & TF_RCVD_SCALE))) { *((u_int32_t *)(opt + optlen)) = htonl( TCPOPT_NOP << 24 | TCPOPT_WINDOW << 16 | TCPOLEN_WINDOW << 8 | tp->request_r_scale); optlen += 4; } } } /* * Send a timestamp and echo-reply if this is a SYN and our side * wants to use timestamps (TF_REQ_TSTMP is set) or both our side * and our peer have sent timestamps in our SYN's. */ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && (flags & TH_RST) == 0 && ((flags & TH_ACK) == 0 || (tp->t_flags & TF_RCVD_TSTMP))) { u_int32_t *lp = (u_int32_t *)(opt + optlen); /* Form timestamp option as shown in appendix A of RFC 1323. */ *lp++ = htonl(TCPOPT_TSTAMP_HDR); *lp++ = htonl(ticks); *lp = htonl(tp->ts_recent); optlen += TCPOLEN_TSTAMP_APPA; } /* * Send SACKs if necessary. This should be the last option processed. * Only as many SACKs are sent as are permitted by the maximum options * size. No more than three SACKs are sent. */ if (tp->sack_enable && tp->t_state == TCPS_ESTABLISHED && (tp->t_flags & (TF_SACK_PERMIT|TF_NOOPT)) == TF_SACK_PERMIT && tp->rcv_numsacks) { u_int32_t *lp = (u_int32_t *)(opt + optlen); u_int32_t *olp = lp++; int count = 0; /* actual number of SACKs inserted */ int maxsack = (MAX_TCPOPTLEN - (optlen + 4))/TCPOLEN_SACK; tcpstat.tcps_sack_send_blocks++; maxsack = min(maxsack, TCP_MAX_SACK); for (i = 0; (i < tp->rcv_numsacks && count < maxsack); i++) { struct sackblk sack = tp->sackblks[i]; if (sack.start == 0 && sack.end == 0) continue; *lp++ = htonl(sack.start); *lp++ = htonl(sack.end); count++; } *olp = htonl(TCPOPT_SACK_HDR|(TCPOLEN_SACK*count+2)); optlen += TCPOLEN_SACK*count + 4; /* including leading NOPs */ } /* * Send `CC-family' options if our side wants to use them (TF_REQ_CC), * options are allowed (!TF_NOOPT) and it's not a RST. */ if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC && (flags & TH_RST) == 0) { switch (flags & (TH_SYN|TH_ACK)) { /* * This is a normal ACK, send CC if we received CC before * from our peer. */ case TH_ACK: if (!(tp->t_flags & TF_RCVD_CC)) break; /*FALLTHROUGH*/ /* * We can only get here in T/TCP's SYN_SENT* state, when * we're a sending a non-SYN segment without waiting for * the ACK of our SYN. A check above assures that we only * do this if our peer understands T/TCP. */ case 0: opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_CC; opt[optlen++] = TCPOLEN_CC; *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send); optlen += 4; break; /* * This is our initial SYN, check whether we have to use * CC or CC.new. */ case TH_SYN: opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_NOP; opt[optlen++] = tp->t_flags & TF_SENDCCNEW ? TCPOPT_CCNEW : TCPOPT_CC; opt[optlen++] = TCPOLEN_CC; *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send); optlen += 4; break; /* * This is a SYN,ACK; send CC and CC.echo if we received * CC from our peer. */ case (TH_SYN|TH_ACK): if (tp->t_flags & TF_RCVD_CC) { opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_CC; opt[optlen++] = TCPOLEN_CC; *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send); optlen += 4; opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_NOP; opt[optlen++] = TCPOPT_CCECHO; opt[optlen++] = TCPOLEN_CC; *(u_int32_t *)&opt[optlen] = htonl(tp->cc_recv); optlen += 4; } break; } } #ifdef TCP_SIGNATURE #ifdef INET6 if (!isipv6) #endif if (tp->t_flags & TF_SIGNATURE) { int i; u_char *bp; /* Initialize TCP-MD5 option (RFC2385) */ bp = (u_char *)opt + optlen; *bp++ = TCPOPT_SIGNATURE; *bp++ = TCPOLEN_SIGNATURE; sigoff = optlen + 2; for (i = 0; i < TCP_SIGLEN; i++) *bp++ = 0; optlen += TCPOLEN_SIGNATURE; /* Terminate options list and maintain 32-bit alignment. */ *bp++ = TCPOPT_NOP; *bp++ = TCPOPT_EOL; optlen += 2; } #endif /* TCP_SIGNATURE */ hdrlen += optlen; #ifdef INET6 if (isipv6) ipoptlen = ip6_optlen(tp->t_inpcb); else #endif if (tp->t_inpcb->inp_options) ipoptlen = tp->t_inpcb->inp_options->m_len - offsetof(struct ipoption, ipopt_list); else
/* collect MSTS sentence from tty */ int mstsinput(int c, struct tty *tp) { struct msts *np = (struct msts *)tp->t_sc; struct timespec ts; int64_t gap; long tmin, tmax; switch (c) { case 2: /* ASCII <STX> */ nanotime(&ts); np->pos = np->sync = 0; gap = (ts.tv_sec * 1000000000LL + ts.tv_nsec) - (np->lts.tv_sec * 1000000000LL + np->lts.tv_nsec); np->lts.tv_sec = ts.tv_sec; np->lts.tv_nsec = ts.tv_nsec; if (gap <= np->gap) break; np->ts.tv_sec = ts.tv_sec; np->ts.tv_nsec = ts.tv_nsec; np->gap = gap; /* * If a tty timestamp is available, make sure its value is * reasonable by comparing against the timestamp just taken. * If they differ by more than 2 seconds, assume no PPS signal * is present, note the fact, and keep using the timestamp * value. When this happens, the sensor state is set to * CRITICAL later when the MSTS sentence is decoded. */ if (tp->t_flags & (TS_TSTAMPDCDSET | TS_TSTAMPDCDCLR | TS_TSTAMPCTSSET | TS_TSTAMPCTSCLR)) { tmax = lmax(np->ts.tv_sec, tp->t_tv.tv_sec); tmin = lmin(np->ts.tv_sec, tp->t_tv.tv_sec); if (tmax - tmin > 1) np->no_pps = 1; else { np->ts.tv_sec = tp->t_tv.tv_sec; np->ts.tv_nsec = tp->t_tv.tv_usec * 1000L; np->no_pps = 0; } } break; case 3: /* ASCII <ETX> */ if (!np->sync) { np->cbuf[np->pos] = '\0'; msts_scan(np, tp); np->sync = 1; } break; default: if (!np->sync && np->pos < (MSTSMAX - 1)) np->cbuf[np->pos++] = c; break; } /* pass data to termios */ return linesw[TTYDISC].l_rint(c, tp); }
Rect Rect::unionRect(const Rect & r) const { return Rect(lmin(m_iLeft, r.m_iLeft), lmax(m_iTop, r.m_iTop), lmax(m_iRight, r.m_iRight), lmin(m_iBottom, r.m_iBottom)); }
/* collect EndRun sentence from tty */ int endruninput(int c, struct tty *tp) { struct endrun *np = (struct endrun *)tp->t_sc; struct timespec ts; int64_t gap; long tmin, tmax; if (np->sync == SYNC_EOL) { nanotime(&ts); np->pos = 0; np->sync = SYNC_SCAN; np->cbuf[np->pos++] = c; /* TFOM char */ gap = (ts.tv_sec * 1000000000LL + ts.tv_nsec) - (np->lts.tv_sec * 1000000000LL + np->lts.tv_nsec); np->lts.tv_sec = ts.tv_sec; np->lts.tv_nsec = ts.tv_nsec; if (gap <= np->gap) goto nogap; np->ts.tv_sec = ts.tv_sec; np->ts.tv_nsec = ts.tv_nsec; np->gap = gap; /* * If a tty timestamp is available, make sure its value is * reasonable by comparing against the timestamp just taken. * If they differ by more than 2 seconds, assume no PPS signal * is present, note the fact, and keep using the timestamp * value. When this happens, the sensor state is set to * CRITICAL later when the EndRun sentence is decoded. */ if (tp->t_flags & (TS_TSTAMPDCDSET | TS_TSTAMPDCDCLR | TS_TSTAMPCTSSET | TS_TSTAMPCTSCLR)) { tmax = lmax(np->ts.tv_sec, tp->t_tv.tv_sec); tmin = lmin(np->ts.tv_sec, tp->t_tv.tv_sec); if (tmax - tmin > 1) np->no_pps = 1; else { np->ts.tv_sec = tp->t_tv.tv_sec; np->ts.tv_nsec = tp->t_tv.tv_usec * 1000L; np->no_pps = 0; } } } else if (c == '\n') { if (np->pos == ENDRUNLEN - 1) { /* don't copy '\n' into cbuf */ np->cbuf[np->pos] = '\0'; endrun_scan(np, tp); } np->sync = SYNC_EOL; } else { if (np->pos < ENDRUNLEN - 1) np->cbuf[np->pos++] = c; } nogap: /* pass data to termios */ return linesw[TTYDISC].l_rint(c, tp); }
/* * Slightly changed version of sosend() */ static int kttcp_sosend(struct socket *so, unsigned long long slen, unsigned long long *done, struct lwp *l, int flags) { struct mbuf **mp, *m, *top; long space, len, mlen; int error, dontroute, atomic; long long resid; atomic = sosendallatonce(so); resid = slen; top = NULL; /* * In theory resid should be unsigned. * However, space must be signed, as it might be less than 0 * if we over-committed, and we must use a signed comparison * of space and resid. On the other hand, a negative resid * causes us to loop sending 0-length segments to the protocol. */ if (resid < 0) { error = EINVAL; goto out; } dontroute = (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && (so->so_proto->pr_flags & PR_ATOMIC); l->l_ru.ru_msgsnd++; #define snderr(errno) { error = errno; goto release; } solock(so); restart: if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0) goto out; do { if (so->so_state & SS_CANTSENDMORE) snderr(EPIPE); if (so->so_error) { error = so->so_error; so->so_error = 0; goto release; } if ((so->so_state & SS_ISCONNECTED) == 0) { if (so->so_proto->pr_flags & PR_CONNREQUIRED) { snderr(ENOTCONN); } else { snderr(EDESTADDRREQ); } } space = sbspace(&so->so_snd); if (flags & MSG_OOB) space += 1024; if ((atomic && resid > so->so_snd.sb_hiwat)) snderr(EMSGSIZE); if (space < resid && (atomic || space < so->so_snd.sb_lowat)) { if (so->so_state & SS_NBIO) snderr(EWOULDBLOCK); SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive sbwait 1"); SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive sbwait 1"); sbunlock(&so->so_snd); error = sbwait(&so->so_snd); if (error) goto out; goto restart; } mp = ⊤ do { sounlock(so); do { if (top == 0) { m = m_gethdr(M_WAIT, MT_DATA); mlen = MHLEN; m->m_pkthdr.len = 0; m->m_pkthdr.rcvif = NULL; } else { m = m_get(M_WAIT, MT_DATA); mlen = MLEN; } if (resid >= MINCLSIZE && space >= MCLBYTES) { m_clget(m, M_WAIT); if ((m->m_flags & M_EXT) == 0) goto nopages; mlen = MCLBYTES; #ifdef MAPPED_MBUFS len = lmin(MCLBYTES, resid); #else if (atomic && top == 0) { len = lmin(MCLBYTES - max_hdr, resid); m->m_data += max_hdr; } else len = lmin(MCLBYTES, resid); #endif space -= len; } else { nopages: len = lmin(lmin(mlen, resid), space); space -= len; /* * For datagram protocols, leave room * for protocol headers in first mbuf. */ if (atomic && top == 0 && len < mlen) MH_ALIGN(m, len); } resid -= len; m->m_len = len; *mp = m; top->m_pkthdr.len += len; if (error) goto release; mp = &m->m_next; if (resid <= 0) { if (flags & MSG_EOR) top->m_flags |= M_EOR; break; } } while (space > 0 && atomic); solock(so); if (so->so_state & SS_CANTSENDMORE) snderr(EPIPE); if (dontroute) so->so_options |= SO_DONTROUTE; if (resid > 0) so->so_state |= SS_MORETOCOME; if (flags & MSG_OOB) error = (*so->so_proto->pr_usrreqs->pr_sendoob)(so, top, NULL); else error = (*so->so_proto->pr_usrreqs->pr_send)(so, top, NULL, NULL, l); if (dontroute) so->so_options &= ~SO_DONTROUTE; if (resid > 0) so->so_state &= ~SS_MORETOCOME; top = 0; mp = ⊤ if (error) goto release; } while (resid && space > 0); } while (resid); release: sbunlock(&so->so_snd); out: sounlock(so); if (top) m_freem(top); *done = slen - resid; #if 0 printf("sosend: error %d slen %llu resid %lld\n", error, slen, resid); #endif return (error); }
/* Subroutine */ int zungbr_(char *vect, integer *m, integer *n, integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex * work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; /* Local variables */ integer i__, j, nb, mn; extern logical lsame_(char *, char *); integer iinfo; logical wantq; extern /* Subroutine */ int xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); integer lwkopt; logical lquery; extern /* Subroutine */ int zunglq_(integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, integer *), zungqr_(integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *, integer *); /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZUNGBR generates one of the complex unitary matrices Q or P**H */ /* determined by ZGEBRD when reducing a complex matrix A to bidiagonal */ /* form: A = Q * B * P**H. Q and P**H are defined as products of */ /* elementary reflectors H(i) or G(i) respectively. */ /* If VECT = 'Q', A is assumed to have been an M-by-K matrix, and Q */ /* is of order M: */ /* if m >= k, Q = H(1) H(2) . . . H(k) and ZUNGBR returns the first n */ /* columns of Q, where m >= n >= k; */ /* if m < k, Q = H(1) H(2) . . . H(m-1) and ZUNGBR returns Q as an */ /* M-by-M matrix. */ /* If VECT = 'P', A is assumed to have been a K-by-N matrix, and P**H */ /* is of order N: */ /* if k < n, P**H = G(k) . . . G(2) G(1) and ZUNGBR returns the first m */ /* rows of P**H, where n >= m >= k; */ /* if k >= n, P**H = G(n-1) . . . G(2) G(1) and ZUNGBR returns P**H as */ /* an N-by-N matrix. */ /* Arguments */ /* ========= */ /* VECT (input) CHARACTER*1 */ /* Specifies whether the matrix Q or the matrix P**H is */ /* required, as defined in the transformation applied by ZGEBRD: */ /* = 'Q': generate Q; */ /* = 'P': generate P**H. */ /* M (input) INTEGER */ /* The number of rows of the matrix Q or P**H to be returned. */ /* M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix Q or P**H to be returned. */ /* N >= 0. */ /* If VECT = 'Q', M >= N >= lmin(M,K); */ /* if VECT = 'P', N >= M >= lmin(N,K). */ /* K (input) INTEGER */ /* If VECT = 'Q', the number of columns in the original M-by-K */ /* matrix reduced by ZGEBRD. */ /* If VECT = 'P', the number of rows in the original K-by-N */ /* matrix reduced by ZGEBRD. */ /* K >= 0. */ /* A (input/output) COMPLEX*16 array, dimension (LDA,N) */ /* On entry, the vectors which define the elementary reflectors, */ /* as returned by ZGEBRD. */ /* On exit, the M-by-N matrix Q or P**H. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. LDA >= M. */ /* TAU (input) COMPLEX*16 array, dimension */ /* (min(M,K)) if VECT = 'Q' */ /* (min(N,K)) if VECT = 'P' */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i) or G(i), which determines Q or P**H, as */ /* returned by ZGEBRD in its array argument TAUQ or TAUP. */ /* WORK (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= lmax(1,min(M,N)). */ /* For optimum performance LWORK >= lmin(M,N)*NB, where NB */ /* is the optimal blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; --work; /* Function Body */ *info = 0; wantq = lsame_(vect, "Q"); mn = lmin(*m,*n); lquery = *lwork == -1; if (! wantq && ! lsame_(vect, "P")) { *info = -1; } else if (*m < 0) { *info = -2; } else if (*n < 0 || wantq && (*n > *m || *n < lmin(*m,*k)) || ! wantq && ( *m > *n || *m < lmin(*n,*k))) { *info = -3; } else if (*k < 0) { *info = -4; } else if (*lda < lmax(1,*m)) { *info = -6; } else if (*lwork < lmax(1,mn) && ! lquery) { *info = -9; } if (*info == 0) { if (wantq) { nb = ilaenv_(&c__1, "ZUNGQR", " ", m, n, k, &c_n1); } else { nb = ilaenv_(&c__1, "ZUNGLQ", " ", m, n, k, &c_n1); } lwkopt = lmax(1,mn) * nb; work[1].r = (doublereal) lwkopt, work[1].i = 0.; } if (*info != 0) { i__1 = -(*info); xerbla_("ZUNGBR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*m == 0 || *n == 0) { work[1].r = 1., work[1].i = 0.; return 0; } if (wantq) { /* Form Q, determined by a call to ZGEBRD to reduce an m-by-k */ /* matrix */ if (*m >= *k) { /* If m >= k, assume m >= n >= k */ zungqr_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If m < k, assume m = n */ /* Shift the vectors which define the elementary reflectors one */ /* column to the right, and set the first row and column of Q */ /* to those of the unit matrix */ for (j = *m; j >= 2; --j) { i__1 = j * a_dim1 + 1; a[i__1].r = 0., a[i__1].i = 0.; i__1 = *m; for (i__ = j + 1; i__ <= i__1; ++i__) { i__2 = i__ + j * a_dim1; i__3 = i__ + (j - 1) * a_dim1; a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i; /* L10: */ } /* L20: */ } i__1 = a_dim1 + 1; a[i__1].r = 1., a[i__1].i = 0.; i__1 = *m; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = i__ + a_dim1; a[i__2].r = 0., a[i__2].i = 0.; /* L30: */ } if (*m > 1) { /* Form Q(2:m,2:m) */ i__1 = *m - 1; i__2 = *m - 1; i__3 = *m - 1; zungqr_(&i__1, &i__2, &i__3, &a[(a_dim1 << 1) + 2], lda, &tau[ 1], &work[1], lwork, &iinfo); } } } else { /* Form P', determined by a call to ZGEBRD to reduce a k-by-n */ /* matrix */ if (*k < *n) { /* If k < n, assume k <= m <= n */ zunglq_(m, n, k, &a[a_offset], lda, &tau[1], &work[1], lwork, & iinfo); } else { /* If k >= n, assume m = n */ /* Shift the vectors which define the elementary reflectors one */ /* row downward, and set the first row and column of P' to */ /* those of the unit matrix */ i__1 = a_dim1 + 1; a[i__1].r = 1., a[i__1].i = 0.; i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { i__2 = i__ + a_dim1; a[i__2].r = 0., a[i__2].i = 0.; /* L40: */ } i__1 = *n; for (j = 2; j <= i__1; ++j) { for (i__ = j - 1; i__ >= 2; --i__) { i__2 = i__ + j * a_dim1; i__3 = i__ - 1 + j * a_dim1; a[i__2].r = a[i__3].r, a[i__2].i = a[i__3].i; /* L50: */ } i__2 = j * a_dim1 + 1; a[i__2].r = 0., a[i__2].i = 0.; /* L60: */ } if (*n > 1) { /* Form P'(2:n,2:n) */ i__1 = *n - 1; i__2 = *n - 1; i__3 = *n - 1; zunglq_(&i__1, &i__2, &i__3, &a[(a_dim1 << 1) + 2], lda, &tau[ 1], &work[1], lwork, &iinfo); } } } work[1].r = (doublereal) lwkopt, work[1].i = 0.; return 0; /* End of ZUNGBR */ } /* zungbr_ */
void compute(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[], const int atria_preprocessing_given, METRIC dummy) { long bins = 32; double start_dist = 0; double maximal_search_radius = 0; double scale_factor = 1; long opt_flag = 0; // 0 => eucl.norm, upper triangle matrix, 1 => max.norm, utm, 2 => eucl,full matrix, 3 => max.,full matrix long Nref_min; long Nref_max; /* handle matrix I/O */ #ifdef C_STYLE_POINT_SET const long N = mxGetN(prhs[0]); const long dim = mxGetM(prhs[0]); #else // this is the default const long N = mxGetM(prhs[0]); const long dim = mxGetN(prhs[0]); #endif const double* p = (double *)mxGetPr(prhs[0]); const long Npairs = (long) *((double *)mxGetPr(prhs[1])); // number of pairs if (mxGetM(prhs[1])*mxGetN(prhs[1]) == 3) { Nref_min = (long) ((double *)mxGetPr(prhs[1]))[1]; Nref_max = (long) ((double *)mxGetPr(prhs[1]))[2]; } else { Nref_min = 1; Nref_max = N; } const double relative_range = (double) *((double *)mxGetPr(prhs[2])); const long past = (long) *((double *)mxGetPr(prhs[3])); if (nrhs > 4) bins = (long) *((double *)mxGetPr(prhs[4])); if (nrhs > 5) opt_flag = (long) *((double *)mxGetPr(prhs[5])); if (N < 1) { mexErrMsgTxt("Data set must consist of at least two points (row vectors)"); return; } if (dim < 1) { mexErrMsgTxt("Data points must be at least of dimension one"); return; } if (relative_range <= 0) { mexErrMsgTxt("Relative range must be greater zero"); return; } if (bins < 2) { mexErrMsgTxt("Number of bins should be two"); return; } if (Npairs < 1) { mexErrMsgTxt("Number of pairs must be positive"); return; } if ((opt_flag < 0) || (opt_flag > 7)) { mexErrMsgTxt("Flag must be out of 0..7"); return; } if (Nref_min < 1) Nref_min = 1; if (Nref_max > N) Nref_max = N; point_set<METRIC> points(N,dim, p); ATRIA< point_set<METRIC> >* searcher = 0; #ifdef MATLAB_MEX_FILE if (atria_preprocessing_given) { searcher = new ATRIA< point_set<METRIC> >(points, prhs[-1]); // this constructor used the data from the preprocessing if (searcher->geterr()) { delete searcher; searcher = 0; } } #endif if (searcher == 0) { searcher = new ATRIA< point_set<METRIC> >(points); } if (searcher->geterr()) { mexErrMsgTxt("Error preparing searcher"); return; } if (mxGetM(prhs[2])*mxGetN(prhs[2]) == 2) { start_dist = (double) ((double *)mxGetPr(prhs[2]))[0]; maximal_search_radius = (double) ((double *)mxGetPr(prhs[2]))[1]; if (start_dist <= 0) { mexErrMsgTxt("Starting radius is zero or negativ"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } else { maximal_search_radius = relative_range * searcher->data_set_radius(); // compute the maximal search radius using information about attractor size // try to determine an estimate for the minimum inter-point distance in the data set, but greater zero for (long n=0; n < 128; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; searcher->search_k_neighbors(v, 1, points.point_begin(actual), actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } if (start_dist <= 0) { // first try to search again for a minimum inter-point distance greater zero for (long n=0; n < 512; n++) { const long actual = (long) (((double)rand() * (double) (N-2))/(double)RAND_MAX); vector<neighbor> v; searcher->search_k_neighbors(v, 1, points.point_begin(actual), actual, actual); // search the nearest neighbor if (v.size() > 0) { if (start_dist == 0) start_dist = v[0].dist(); if (v[0].dist() > 0) { if (v[0].dist() < start_dist) start_dist = v[0].dist(); } } } } if (start_dist <= 0) { // give up if we cannot find an interpoint distance greater zero mexErrMsgTxt("Cannot find an interpoint distance greater zero, maybe ill-conditioned data set given"); return; } if (maximal_search_radius <= start_dist) { mexErrMsgTxt("Maximal search radius must be greater than starting radius"); return; } } scale_factor = pow(maximal_search_radius/start_dist, 1.0/(bins-1)); if (be_verbose) { //mexPrintf("Number of reference points : %d\n", R); mexPrintf("Number of data set points : %d\n", N); mexPrintf("Number of pairs to find : %d\n", Npairs); mexPrintf("Miniumum number of reference points : %d\n", Nref_min); mexPrintf("Maximum number of reference points : %d\n", Nref_max); mexPrintf("Upper bound for attractor size : %f\n", 2 * searcher->data_set_radius()); mexPrintf("Number of partitions used : %d\n", bins); mexPrintf("Time window to exclude from search : %d\n", past); mexPrintf("Minimal length scale : %f\n", start_dist); mexPrintf("Starting at maximal length scale : %f\n", maximal_search_radius); } plhs[0] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* corrsums = (double *) mxGetPr(plhs[0]); long* const ref = new long[N]; // needed to create random reference indices long* const total_pairs = new long[bins]; // number of total pairs is not equal for all bins long* const pairs_found = new long[bins]; // number of pairs found within distance dist double* dists; if (nlhs > 1) { plhs[1] = mxCreateDoubleMatrix(bins, 1, mxREAL); dists = (double *) mxGetPr(plhs[1]); } else dists = new double[bins]; double x = start_dist; // initialize vectors // pairs_found[i] counts the number of points/distances (real) smaller than dists[i] for (long bin=0; bin < bins; bin++) { pairs_found[bin] = 0; total_pairs[bin] = 0; dists[bin] = x; x *= scale_factor; } for (long r=0; r < N; r++) ref[r] = r; long R = 0; // number of reference points actually used long bin = bins-1; // the current highest bin (and length scale) that needs to be filled over Npairs while(((R < Nref_min) || (pairs_found[bin] < Npairs)) && (R < Nref_max)) { vector<neighbor> v; long first, last; // all points with indices i so that first <= i <= last are excluded(!) from search long pairs = 0; const long actual = random_permutation(ref, N, R++); // choose random index from 0...N-1, without reoccurences if (opt_flag & (long)2) { first = actual-past; last = actual+past; if (past >= 0) pairs = lmax(0,first) + lmax(N-1-last,0); else pairs = N; } else { if (past >= 0) first = actual-past; else first = actual; last = N; pairs = lmin(first,last); // don't search points from [actual-past .. N-1] } if (pairs <= 0) { continue; } searcher->search_range(v, dists[bin], points.point_begin(actual), first, last); if (v.size() > 0) { for (vector<neighbor>::iterator i = v.begin(); i < v.end(); i++) { // v is unsorted (!!!) const double d = (*i).dist(); for (long n = bin; n >= 0; n--) { if (d > dists[n]) break; pairs_found[n]++; } } } for (long n = 0; n <= bin; n++) { total_pairs[n] += pairs; } // see if we can reduce length scale int bins_changed = 0; while((pairs_found[bin] >= Npairs) && (bin > 0) && (R >= Nref_min)) { bin--; bins_changed = 1; } if (be_verbose) { if (bins_changed) { mexPrintf("Reference points used so far : %d\n", R); mexPrintf("Switching to length scale : %f\n", dists[bin]); } } } if (be_verbose) { mexPrintf("Number of reference points used : %d\n", R); } for (long bin=0; bin < bins; bin++) { corrsums[bin] = ((double) pairs_found[bin]) / ((double) total_pairs[bin]); } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* const y = mxGetPr(plhs[2]); for (long b=0; b < bins; b++) y[b] = (double) pairs_found[b]; } if (nlhs > 3) { plhs[3] = mxCreateDoubleMatrix(bins, 1, mxREAL); double* const y = mxGetPr(plhs[3]); for (long b=0; b < bins; b++) y[b] = (double) total_pairs[b]; } if (nlhs > 4) { plhs[4] = mxCreateDoubleMatrix(R, 1, mxREAL); double* const y = mxGetPr(plhs[4]); for (long r=0; r < R; r++) y[r] = (double) ref[r]+1; // C to Matlab means } delete[] total_pairs; delete[] pairs_found; delete[] ref; if (!(nlhs > 1)) delete[] dists; delete searcher; }
/* called at end of declarations section to process chains created by EQUIVALENCE statements */ void doequiv(Void) { register int i; int inequiv; /* True if one namep occurs in several EQUIV declarations */ int comno; /* Index into Extsym table of the last COMMON block seen (implicitly assuming that only one will be given) */ int ovarno; ftnint comoffset; /* Index into the COMMON block */ ftnint offset; /* Offset from array base */ ftnint leng; register struct Equivblock *equivdecl; register struct Eqvchain *q; struct Primblock *primp; register Namep np; int k, k1, ns, pref, t; chainp cp; extern int type_pref[]; char *s; for(i = 0 ; i < nequiv ; ++i) { /* Handle each equivalence declaration */ equivdecl = &eqvclass[i]; equivdecl->eqvbottom = equivdecl->eqvtop = 0; comno = -1; for(q = equivdecl->equivs ; q ; q = q->eqvnextp) { offset = 0; if (!(primp = q->eqvitem.eqvlhs)) continue; vardcl(np = primp->namep); if(primp->argsp || primp->fcharp) { expptr offp; /* Pad ones onto the end of an array declaration when needed */ if(np->vdim!=NULL && np->vdim->ndim>1 && nsubs(primp->argsp)==1 ) { if(! ftn66flag) warni ("1-dim subscript in EQUIVALENCE, %d-dim declared", np -> vdim -> ndim); cp = NULL; ns = np->vdim->ndim; while(--ns > 0) cp = mkchain((char *)ICON(1), cp); primp->argsp->listp->nextp = cp; } offp = suboffset(primp); if(ISICON(offp)) offset = offp->constblock.Const.ci; else { dclerr ("nonconstant subscript in equivalence ", np); np = NULL; } frexpr(offp); } /* Free up the primblock, since we now have a hash table (Namep) entry */ frexpr((expptr)primp); if(np && (leng = iarrlen(np))<0) { dclerr("adjustable in equivalence", np); np = NULL; } if(np) switch(np->vstg) { case STGUNKNOWN: case STGBSS: case STGEQUIV: break; case STGCOMMON: /* The code assumes that all COMMON references in a given EQUIVALENCE will be to the same COMMON block, and will all be consistent */ comno = np->vardesc.varno; comoffset = np->voffset + offset; break; default: dclerr("bad storage class in equivalence", np); np = NULL; break; } if(np) { q->eqvoffset = offset; /* eqvbottom gets the largest difference between the array base address and the address specified in the EQUIV declaration */ equivdecl->eqvbottom = lmin(equivdecl->eqvbottom, -offset); /* eqvtop gets the largest difference between the end of the array and the address given in the EQUIVALENCE */ equivdecl->eqvtop = lmax(equivdecl->eqvtop, leng-offset); } q->eqvitem.eqvname = np; } /* Now all equivalenced variables are in the hash table with the proper offset, and eqvtop and eqvbottom are set. */ if(comno >= 0) /* Get rid of all STGEQUIVS, they will be mapped onto STGCOMMON variables */ eqvcommon(equivdecl, comno, comoffset); else for(q = equivdecl->equivs ; q ; q = q->eqvnextp) { if(np = q->eqvitem.eqvname) { inequiv = NO; if(np->vstg==STGEQUIV) if( (ovarno = np->vardesc.varno) == i) { /* Can't EQUIV different elements of the same array */ if(np->voffset + q->eqvoffset != 0) dclerr ("inconsistent equivalence", np); } else { offset = np->voffset; inequiv = YES; } np->vstg = STGEQUIV; np->vardesc.varno = i; np->voffset = - q->eqvoffset; if(inequiv) /* Combine 2 equivalence declarations */ eqveqv(i, ovarno, q->eqvoffset + offset); } } } /* Now each equivalence declaration is distinct (all connections have been merged in eqveqv()), and some may be empty. */ for(i = 0 ; i < nequiv ; ++i) { equivdecl = & eqvclass[i]; if(equivdecl->eqvbottom!=0 || equivdecl->eqvtop!=0) { /* a live chain */ k = TYCHAR; pref = 1; for(q = equivdecl->equivs ; q; q = q->eqvnextp) if ((np = q->eqvitem.eqvname) && !np->veqvadjust) { np->veqvadjust = 1; np->voffset -= equivdecl->eqvbottom; t = typealign[k1 = np->vtype]; if (pref < type_pref[k1]) { k = k1; pref = type_pref[k1]; } if(np->voffset % t != 0) { dclerr("bad alignment forced by equivalence", np); --nerr; /* don't give bad return code for this */ } } equivdecl->eqvtype = k; } freqchain(equivdecl); } }
/* Subroutine */ int zungqr_(integer *m, integer *n, integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex * work, integer *lwork, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3, i__4; /* Local variables */ integer i__, j, l, ib, nb, ki, kk, nx, iws, nbmin, iinfo; extern /* Subroutine */ int zung2r_(integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *), xerbla_(char *, integer *); extern integer ilaenv_(integer *, char *, char *, integer *, integer *, integer *, integer *); extern /* Subroutine */ int zlarfb_(char *, char *, char *, char *, integer *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *, doublecomplex *, integer *); integer ldwork; extern /* Subroutine */ int zlarft_(char *, char *, integer *, integer *, doublecomplex *, integer *, doublecomplex *, doublecomplex *, integer *); integer lwkopt; logical lquery; /* -- LAPACK routine (version 3.2) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* ZUNGQR generates an M-by-N complex matrix Q with orthonormal columns, */ /* which is defined as the first N columns of a product of K elementary */ /* reflectors of order M */ /* Q = H(1) H(2) . . . H(k) */ /* as returned by ZGEQRF. */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix Q. M >= 0. */ /* N (input) INTEGER */ /* The number of columns of the matrix Q. M >= N >= 0. */ /* K (input) INTEGER */ /* The number of elementary reflectors whose product defines the */ /* matrix Q. N >= K >= 0. */ /* A (input/output) COMPLEX*16 array, dimension (LDA,N) */ /* On entry, the i-th column must contain the vector which */ /* defines the elementary reflector H(i), for i = 1,2,...,k, as */ /* returned by ZGEQRF in the first k columns of its array */ /* argument A. */ /* On exit, the M-by-N matrix Q. */ /* LDA (input) INTEGER */ /* The first dimension of the array A. LDA >= lmax(1,M). */ /* TAU (input) COMPLEX*16 array, dimension (K) */ /* TAU(i) must contain the scalar factor of the elementary */ /* reflector H(i), as returned by ZGEQRF. */ /* WORK (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. LWORK >= lmax(1,N). */ /* For optimum performance LWORK >= N*NB, where NB is the */ /* optimal blocksize. */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument has an illegal value */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input arguments */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --tau; --work; /* Function Body */ *info = 0; nb = ilaenv_(&c__1, "ZUNGQR", " ", m, n, k, &c_n1); lwkopt = lmax(1,*n) * nb; work[1].r = (doublereal) lwkopt, work[1].i = 0.; lquery = *lwork == -1; if (*m < 0) { *info = -1; } else if (*n < 0 || *n > *m) { *info = -2; } else if (*k < 0 || *k > *n) { *info = -3; } else if (*lda < lmax(1,*m)) { *info = -5; } else if (*lwork < lmax(1,*n) && ! lquery) { *info = -8; } if (*info != 0) { i__1 = -(*info); xerbla_("ZUNGQR", &i__1); return 0; } else if (lquery) { return 0; } /* Quick return if possible */ if (*n <= 0) { work[1].r = 1., work[1].i = 0.; return 0; } nbmin = 2; nx = 0; iws = *n; if (nb > 1 && nb < *k) { /* Determine when to cross over from blocked to unblocked code. */ /* Computing MAX */ i__1 = 0, i__2 = ilaenv_(&c__3, "ZUNGQR", " ", m, n, k, &c_n1); nx = lmax(i__1,i__2); if (nx < *k) { /* Determine if workspace is large enough for blocked code. */ ldwork = *n; iws = ldwork * nb; if (*lwork < iws) { /* Not enough workspace to use optimal NB: reduce NB and */ /* determine the minimum value of NB. */ nb = *lwork / ldwork; /* Computing MAX */ i__1 = 2, i__2 = ilaenv_(&c__2, "ZUNGQR", " ", m, n, k, &c_n1); nbmin = lmax(i__1,i__2); } } } if (nb >= nbmin && nb < *k && nx < *k) { /* Use blocked code after the last block. */ /* The first kk columns are handled by the block method. */ ki = (*k - nx - 1) / nb * nb; /* Computing MIN */ i__1 = *k, i__2 = ki + nb; kk = lmin(i__1,i__2); /* Set A(1:kk,kk+1:n) to zero. */ i__1 = *n; for (j = kk + 1; j <= i__1; ++j) { i__2 = kk; for (i__ = 1; i__ <= i__2; ++i__) { i__3 = i__ + j * a_dim1; a[i__3].r = 0., a[i__3].i = 0.; /* L10: */ } /* L20: */ } } else { kk = 0; } /* Use unblocked code for the last or only block. */ if (kk < *n) { i__1 = *m - kk; i__2 = *n - kk; i__3 = *k - kk; zung2r_(&i__1, &i__2, &i__3, &a[kk + 1 + (kk + 1) * a_dim1], lda, & tau[kk + 1], &work[1], &iinfo); } if (kk > 0) { /* Use blocked code */ i__1 = -nb; for (i__ = ki + 1; i__1 < 0 ? i__ >= 1 : i__ <= 1; i__ += i__1) { /* Computing MIN */ i__2 = nb, i__3 = *k - i__ + 1; ib = lmin(i__2,i__3); if (i__ + ib <= *n) { /* Form the triangular factor of the block reflector */ /* H = H(i) H(i+1) . . . H(i+ib-1) */ i__2 = *m - i__ + 1; zlarft_("Forward", "Columnwise", &i__2, &ib, &a[i__ + i__ * a_dim1], lda, &tau[i__], &work[1], &ldwork); /* Apply H to A(i:m,i+ib:n) from the left */ i__2 = *m - i__ + 1; i__3 = *n - i__ - ib + 1; zlarfb_("Left", "No transpose", "Forward", "Columnwise", & i__2, &i__3, &ib, &a[i__ + i__ * a_dim1], lda, &work[ 1], &ldwork, &a[i__ + (i__ + ib) * a_dim1], lda, & work[ib + 1], &ldwork); } /* Apply H to rows i:m of current block */ i__2 = *m - i__ + 1; zung2r_(&i__2, &ib, &ib, &a[i__ + i__ * a_dim1], lda, &tau[i__], & work[1], &iinfo); /* Set rows 1:i-1 of current block to zero */ i__2 = i__ + ib - 1; for (j = i__; j <= i__2; ++j) { i__3 = i__ - 1; for (l = 1; l <= i__3; ++l) { i__4 = l + j * a_dim1; a[i__4].r = 0., a[i__4].i = 0.; /* L30: */ } /* L40: */ } /* L50: */ } } work[1].r = (doublereal) iws, work[1].i = 0.; return 0; /* End of ZUNGQR */ } /* zungqr_ */